From 390ed322cb8f40cb9250021cde5f48acb928d291 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 20 Jul 2013 07:24:12 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6001 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src') diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c index fdb802ccc..ca09e9d64 100644 --- a/os/hal/src/serial.c +++ b/os/hal/src/serial.c @@ -133,7 +133,7 @@ void sdInit(void) { void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { sdp->vmt = &vmt; - chEvtInit(&sdp->event); + chEvtObjectInit(&sdp->event); sdp->state = SD_STOP; chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); -- cgit v1.2.3 From 49d71a01abeefa000a4cd7a556052d826b096d49 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 20 Jul 2013 10:12:44 +0000 Subject: Renamed or added prefix to all hernel configuration options. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6010 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/adc.c | 10 +++++----- os/hal/src/i2c.c | 12 ++++++------ os/hal/src/spi.c | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c index d0e814ae2..aeb1f6c6b 100644 --- a/os/hal/src/adc.c +++ b/os/hal/src/adc.c @@ -81,7 +81,7 @@ void adcObjectInit(ADCDriver *adcp) { adcp->thread = NULL; #endif /* ADC_USE_WAIT */ #if ADC_USE_MUTUAL_EXCLUSION -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxInit(&adcp->mutex); #else chSemInit(&adcp->semaphore, 1); @@ -309,9 +309,9 @@ void adcAcquireBus(ADCDriver *adcp) { chDbgCheck(adcp != NULL, "adcAcquireBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxLock(&adcp->mutex); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemWait(&adcp->semaphore); #endif } @@ -329,10 +329,10 @@ void adcReleaseBus(ADCDriver *adcp) { chDbgCheck(adcp != NULL, "adcReleaseBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES (void)adcp; chMtxUnlock(); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemSignal(&adcp->semaphore); #endif } diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 78519cc35..8604488e5 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -78,11 +78,11 @@ void i2cObjectInit(I2CDriver *i2cp) { i2cp->config = NULL; #if I2C_USE_MUTUAL_EXCLUSION -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxInit(&i2cp->mutex); #else chSemInit(&i2cp->semaphore, 1); -#endif /* CH_USE_MUTEXES */ +#endif /* CH_CFG_USE_MUTEXES */ #endif /* I2C_USE_MUTUAL_EXCLUSION */ #if defined(I2C_DRIVER_EXT_INIT_HOOK) @@ -270,9 +270,9 @@ void i2cAcquireBus(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cAcquireBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxLock(&i2cp->mutex); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemWait(&i2cp->semaphore); #endif } @@ -290,9 +290,9 @@ void i2cReleaseBus(I2CDriver *i2cp) { chDbgCheck(i2cp != NULL, "i2cReleaseBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxUnlock(); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemSignal(&i2cp->semaphore); #endif } diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c index 2dc0cc6ee..b2ddf48d2 100644 --- a/os/hal/src/spi.c +++ b/os/hal/src/spi.c @@ -78,7 +78,7 @@ void spiObjectInit(SPIDriver *spip) { spip->thread = NULL; #endif /* SPI_USE_WAIT */ #if SPI_USE_MUTUAL_EXCLUSION -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxInit(&spip->mutex); #else chSemInit(&spip->semaphore, 1); @@ -405,9 +405,9 @@ void spiAcquireBus(SPIDriver *spip) { chDbgCheck(spip != NULL, "spiAcquireBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES chMtxLock(&spip->mutex); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemWait(&spip->semaphore); #endif } @@ -425,10 +425,10 @@ void spiReleaseBus(SPIDriver *spip) { chDbgCheck(spip != NULL, "spiReleaseBus"); -#if CH_USE_MUTEXES +#if CH_CFG_USE_MUTEXES (void)spip; chMtxUnlock(); -#elif CH_USE_SEMAPHORES +#elif CH_CFG_USE_SEMAPHORES chSemSignal(&spip->semaphore); #endif } -- cgit v1.2.3 From 8ca210a4af9fd039e290cfcc309adde543999c1f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Aug 2013 08:24:22 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6108 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/adc.c | 343 ------------------- os/hal/src/can.c | 285 ---------------- os/hal/src/ext.c | 207 ------------ os/hal/src/gpt.c | 268 --------------- os/hal/src/hal.c | 194 ----------- os/hal/src/i2c.c | 303 ----------------- os/hal/src/i2s.c | 179 ---------- os/hal/src/icu.c | 159 --------- os/hal/src/mac.c | 272 --------------- os/hal/src/mmc_spi.c | 878 ------------------------------------------------ os/hal/src/mmcsd.c | 114 ------- os/hal/src/pal.c | 127 ------- os/hal/src/pwm.c | 207 ------------ os/hal/src/rtc.c | 186 ---------- os/hal/src/sdc.c | 575 ------------------------------- os/hal/src/serial.c | 246 -------------- os/hal/src/serial_usb.c | 414 ----------------------- os/hal/src/spi.c | 439 ------------------------ os/hal/src/tm.c | 128 ------- os/hal/src/uart.c | 353 ------------------- os/hal/src/usb.c | 780 ------------------------------------------ 21 files changed, 6657 deletions(-) delete mode 100644 os/hal/src/adc.c delete mode 100644 os/hal/src/can.c delete mode 100644 os/hal/src/ext.c delete mode 100644 os/hal/src/gpt.c delete mode 100644 os/hal/src/hal.c delete mode 100644 os/hal/src/i2c.c delete mode 100644 os/hal/src/i2s.c delete mode 100644 os/hal/src/icu.c delete mode 100644 os/hal/src/mac.c delete mode 100644 os/hal/src/mmc_spi.c delete mode 100644 os/hal/src/mmcsd.c delete mode 100644 os/hal/src/pal.c delete mode 100644 os/hal/src/pwm.c delete mode 100644 os/hal/src/rtc.c delete mode 100644 os/hal/src/sdc.c delete mode 100644 os/hal/src/serial.c delete mode 100644 os/hal/src/serial_usb.c delete mode 100644 os/hal/src/spi.c delete mode 100644 os/hal/src/tm.c delete mode 100644 os/hal/src/uart.c delete mode 100644 os/hal/src/usb.c (limited to 'os/hal/src') diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c deleted file mode 100644 index aeb1f6c6b..000000000 --- a/os/hal/src/adc.c +++ /dev/null @@ -1,343 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file adc.c - * @brief ADC Driver code. - * - * @addtogroup ADC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_ADC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief ADC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void adcInit(void) { - - adc_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p ADCDriver structure. - * - * @param[out] adcp pointer to the @p ADCDriver object - * - * @init - */ -void adcObjectInit(ADCDriver *adcp) { - - adcp->state = ADC_STOP; - adcp->config = NULL; - adcp->samples = NULL; - adcp->depth = 0; - adcp->grpp = NULL; -#if ADC_USE_WAIT - adcp->thread = NULL; -#endif /* ADC_USE_WAIT */ -#if ADC_USE_MUTUAL_EXCLUSION -#if CH_CFG_USE_MUTEXES - chMtxInit(&adcp->mutex); -#else - chSemInit(&adcp->semaphore, 1); -#endif -#endif /* ADC_USE_MUTUAL_EXCLUSION */ -#if defined(ADC_DRIVER_EXT_INIT_HOOK) - ADC_DRIVER_EXT_INIT_HOOK(adcp); -#endif -} - -/** - * @brief Configures and activates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] config pointer to the @p ADCConfig object. Depending on - * the implementation the value can be @p NULL. - * - * @api - */ -void adcStart(ADCDriver *adcp, const ADCConfig *config) { - - chDbgCheck(adcp != NULL, "adcStart"); - - chSysLock(); - chDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "adcStart(), #1", "invalid state"); - adcp->config = config; - adc_lld_start(adcp); - adcp->state = ADC_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcStop(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcStop"); - - chSysLock(); - chDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "adcStop(), #1", "invalid state"); - adc_lld_stop(adcp); - adcp->state = ADC_STOP; - chSysUnlock(); -} - -/** - * @brief Starts an ADC conversion. - * @details Starts an asynchronous conversion operation. - * @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 - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @api - */ -void adcStartConversion(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - - chSysLock(); - adcStartConversionI(adcp, grpp, samples, depth); - chSysUnlock(); -} - -/** - * @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 - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * - * @iclass - */ -void adcStartConversionI(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - - chDbgCheckClassI(); - chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && - ((depth == 1) || ((depth & 1) == 0)), - "adcStartConversionI"); - chDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_COMPLETE) || - (adcp->state == ADC_ERROR), - "adcStartConversionI(), #1", "not ready"); - - adcp->samples = samples; - adcp->depth = depth; - adcp->grpp = grpp; - adcp->state = ADC_ACTIVE; - adc_lld_start_conversion(adcp); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p ADC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcStopConversion(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcStopConversion"); - - chSysLock(); - chDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_ACTIVE), - "adcStopConversion(), #1", "invalid state"); - if (adcp->state != ADC_READY) { - adc_lld_stop_conversion(adcp); - adcp->grpp = NULL; - adcp->state = ADC_READY; - _adc_reset_s(adcp); - } - chSysUnlock(); -} - -/** - * @brief Stops an ongoing conversion. - * @details This function stops the currently ongoing conversion and returns - * the driver in the @p ADC_READY state. If there was no conversion - * being processed then the function does nothing. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @iclass - */ -void adcStopConversionI(ADCDriver *adcp) { - - chDbgCheckClassI(); - chDbgCheck(adcp != NULL, "adcStopConversionI"); - chDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_ACTIVE) || - (adcp->state == ADC_COMPLETE), - "adcStopConversionI(), #1", "invalid state"); - - if (adcp->state != ADC_READY) { - adc_lld_stop_conversion(adcp); - adcp->grpp = NULL; - adcp->state = ADC_READY; - _adc_reset_i(adcp); - } -} - -#if ADC_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Performs an ADC conversion. - * @details Performs a synchronous conversion operation. - * @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 - * with no gaps. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @param[in] grpp pointer to a @p ADCConversionGroup object - * @param[out] samples pointer to the samples buffer - * @param[in] depth buffer depth (matrix rows number). The buffer depth - * must be one or an even number. - * @return The operation result. - * @retval RDY_OK Conversion finished. - * @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 - */ -msg_t adcConvert(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth) { - msg_t msg; - - chSysLock(); - chDbgAssert(adcp->thread == NULL, "adcConvert(), #1", "already waiting"); - adcStartConversionI(adcp, grpp, samples, depth); - adcp->thread = chThdSelf(); - chSchGoSleepS(THD_STATE_SUSPENDED); - msg = chThdSelf()->p_u.rdymsg; - chSysUnlock(); - return msg; -} -#endif /* ADC_USE_WAIT */ - -#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the ADC peripheral. - * @details This function tries to gain ownership to the ADC bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option - * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcAcquireBus(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcAcquireBus"); - -#if CH_CFG_USE_MUTEXES - chMtxLock(&adcp->mutex); -#elif CH_CFG_USE_SEMAPHORES - chSemWait(&adcp->semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the ADC peripheral. - * @pre In order to use this function the option - * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. - * - * @param[in] adcp pointer to the @p ADCDriver object - * - * @api - */ -void adcReleaseBus(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcReleaseBus"); - -#if CH_CFG_USE_MUTEXES - (void)adcp; - chMtxUnlock(); -#elif CH_CFG_USE_SEMAPHORES - chSemSignal(&adcp->semaphore); -#endif -} -#endif /* ADC_USE_MUTUAL_EXCLUSION */ - -#endif /* HAL_USE_ADC */ - -/** @} */ diff --git a/os/hal/src/can.c b/os/hal/src/can.c deleted file mode 100644 index a57f12356..000000000 --- a/os/hal/src/can.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file can.c - * @brief CAN Driver code. - * - * @addtogroup CAN - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_CAN || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief CAN Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void canInit(void) { - - can_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p CANDriver structure. - * - * @param[out] canp pointer to the @p CANDriver object - * - * @init - */ -void canObjectInit(CANDriver *canp) { - - canp->state = CAN_STOP; - canp->config = NULL; - chSemInit(&canp->txsem, 0); - chSemInit(&canp->rxsem, 0); - chEvtInit(&canp->rxfull_event); - chEvtInit(&canp->txempty_event); - chEvtInit(&canp->error_event); -#if CAN_USE_SLEEP_MODE - chEvtInit(&canp->sleep_event); - chEvtInit(&canp->wakeup_event); -#endif /* CAN_USE_SLEEP_MODE */ -} - -/** - * @brief Configures and activates the CAN peripheral. - * @note Activating the CAN bus can be a slow operation this this function - * is not atomic, it waits internally for the initialization to - * complete. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] config pointer to the @p CANConfig object. Depending on - * the implementation the value can be @p NULL. - * - * @api - */ -void canStart(CANDriver *canp, const CANConfig *config) { - - chDbgCheck(canp != NULL, "canStart"); - - chSysLock(); - chDbgAssert((canp->state == CAN_STOP) || - (canp->state == CAN_STARTING) || - (canp->state == CAN_READY), - "canStart(), #1", "invalid state"); - while (canp->state == CAN_STARTING) - chThdSleepS(1); - if (canp->state == CAN_STOP) { - canp->config = config; - can_lld_start(canp); - canp->state = CAN_READY; - } - chSysUnlock(); -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @api - */ -void canStop(CANDriver *canp) { - - chDbgCheck(canp != NULL, "canStop"); - - chSysLock(); - chDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), - "canStop(), #1", "invalid state"); - can_lld_stop(canp); - chSemResetI(&canp->rxsem, 0); - chSemResetI(&canp->txsem, 0); - chSchRescheduleS(); - canp->state = CAN_STOP; - chSysUnlock(); -} - -/** - * @brief Can frame transmission. - * @details The specified frame is queued for transmission, if the hardware - * queue is full then the invoking thread is queued. - * @note Trying to transmit while in sleep mode simply enqueues the thread. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[in] ctfp pointer to the CAN frame to be transmitted - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation result. - * @retval RDY_OK the frame has been queued for transmission. - * @retval RDY_TIMEOUT The operation has timed out. - * @retval RDY_RESET The driver has been stopped while waiting. - * - * @api - */ -msg_t canTransmit(CANDriver *canp, - canmbx_t mailbox, - const CANTxFrame *ctfp, - systime_t timeout) { - - chDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES), - "canTransmit"); - - chSysLock(); - chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canTransmit(), #1", "invalid state"); - while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { - msg_t msg = chSemWaitTimeoutS(&canp->txsem, timeout); - if (msg != RDY_OK) { - chSysUnlock(); - return msg; - } - } - can_lld_transmit(canp, mailbox, ctfp); - chSysUnlock(); - return RDY_OK; -} - -/** - * @brief Can frame receive. - * @details The function waits until a frame is received. - * @note Trying to receive while in sleep mode simply enqueues the thread. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox - * @param[out] crfp pointer to the buffer where the CAN frame is copied - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout (useful in an - * event driven scenario where a thread never blocks - * for I/O). - * - @a TIME_INFINITE no timeout. - * . - * @return The operation result. - * @retval RDY_OK a frame has been received and placed in the buffer. - * @retval RDY_TIMEOUT The operation has timed out. - * @retval RDY_RESET The driver has been stopped while waiting. - * - * @api - */ -msg_t canReceive(CANDriver *canp, - canmbx_t mailbox, - CANRxFrame *crfp, - systime_t timeout) { - - chDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox < CAN_RX_MAILBOXES), - "canReceive"); - - chSysLock(); - chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canReceive(), #1", "invalid state"); - while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { - msg_t msg = chSemWaitTimeoutS(&canp->rxsem, timeout); - if (msg != RDY_OK) { - chSysUnlock(); - return msg; - } - } - can_lld_receive(canp, mailbox, crfp); - chSysUnlock(); - return RDY_OK; -} - -#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * @details This function puts the CAN driver in sleep mode and broadcasts - * the @p sleep_event event source. - * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must - * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported - * by the low level driver. - * - * @param[in] canp pointer to the @p CANDriver object - * - * @api - */ -void canSleep(CANDriver *canp) { - - chDbgCheck(canp != NULL, "canSleep"); - - chSysLock(); - chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canSleep(), #1", "invalid state"); - if (canp->state == CAN_READY) { - can_lld_sleep(canp); - canp->state = CAN_SLEEP; - chEvtBroadcastI(&canp->sleep_event); - chSchRescheduleS(); - } - chSysUnlock(); -} - -/** - * @brief Enforces leaving the sleep mode. - * @note The sleep mode is supposed to be usually exited automatically by - * an hardware event. - * - * @param[in] canp pointer to the @p CANDriver object - */ -void canWakeup(CANDriver *canp) { - - chDbgCheck(canp != NULL, "canWakeup"); - - chSysLock(); - chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canWakeup(), #1", "invalid state"); - if (canp->state == CAN_SLEEP) { - can_lld_wakeup(canp); - canp->state = CAN_READY; - chEvtBroadcastI(&canp->wakeup_event); - chSchRescheduleS(); - } - chSysUnlock(); -} -#endif /* CAN_USE_SLEEP_MODE */ - -#endif /* HAL_USE_CAN */ - -/** @} */ diff --git a/os/hal/src/ext.c b/os/hal/src/ext.c deleted file mode 100644 index a0dc9f38e..000000000 --- a/os/hal/src/ext.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @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 and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* 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. - * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. - * - * @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), - "extChannelEnable"); - - chSysLock(); - chDbgAssert((extp->state == EXT_ACTIVE) && - ((extp->config->channels[channel].mode & - EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), - "extChannelEnable(), #1", "invalid state"); - extChannelEnableI(extp, channel); - chSysUnlock(); -} - -/** - * @brief Disables an EXT channel. - * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. - * - * @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), - "extChannelDisable"); - - chSysLock(); - chDbgAssert((extp->state == EXT_ACTIVE) && - ((extp->config->channels[channel].mode & - EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), - "extChannelDisable(), #1", "invalid state"); - extChannelDisableI(extp, channel); - chSysUnlock(); -} - -/** - * @brief Changes the operation mode of a channel. - * @note This function attempts to write over the current configuration - * structure that must have been not declared constant. This - * violates the @p const qualifier in @p extStart() but it is - * intentional. - * @note This function cannot be used if the configuration structure is - * declared @p const. - * @note The effect of this function on constant configuration structures - * is not defined. - * - * @param[in] extp pointer to the @p EXTDriver object - * @param[in] channel channel to be changed - * @param[in] extcp new configuration for the channel - * - * @iclass - */ -void extSetChannelModeI(EXTDriver *extp, - expchannel_t channel, - const EXTChannelConfig *extcp) { - EXTChannelConfig *oldcp; - - chDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS) && - (extcp != NULL), "extSetChannelModeI"); - - chDbgAssert(extp->state == EXT_ACTIVE, - "extSetChannelModeI(), #1", "invalid state"); - - /* Note that here the access is enforced as non-const, known access - violation.*/ - oldcp = (EXTChannelConfig *)&extp->config->channels[channel]; - - /* Overwiting the old channels configuration then the channel is reconfigured - by the low level driver.*/ - *oldcp = *extcp; - ext_lld_channel_enable(extp, channel); -} - -#endif /* HAL_USE_EXT */ - -/** @} */ diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c deleted file mode 100644 index e37e1a5d8..000000000 --- a/os/hal/src/gpt.c +++ /dev/null @@ -1,268 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file gpt.c - * @brief GPT Driver code. - * - * @addtogroup GPT - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_GPT || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief GPT Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void gptInit(void) { - - gpt_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p GPTDriver structure. - * - * @param[out] gptp pointer to the @p GPTDriver object - * - * @init - */ -void gptObjectInit(GPTDriver *gptp) { - - gptp->state = GPT_STOP; - gptp->config = NULL; -} - -/** - * @brief Configures and activates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] config pointer to the @p GPTConfig object - * - * @api - */ -void gptStart(GPTDriver *gptp, const GPTConfig *config) { - - chDbgCheck((gptp != NULL) && (config != NULL), "ptStart"); - - chSysLock(); - chDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), - "gptStart(), #1", "invalid state"); - gptp->config = config; - gpt_lld_start(gptp); - gptp->state = GPT_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the GPT peripheral. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStop(GPTDriver *gptp) { - - chDbgCheck(gptp != NULL, "gptStop"); - - chSysLock(); - chDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), - "gptStop(), #1", "invalid state"); - gpt_lld_stop(gptp); - gptp->state = GPT_STOP; - chSysUnlock(); -} - -/** - * @brief Changes the interval of GPT peripheral. - * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must have been activated using @p gptStart(). - * @pre The GPT unit must have been running in continuous mode using - * @p gptStartContinuous(). - * @post The GPT unit interval is changed to the new value. - * - * @param[in] gptp pointer to a @p GPTDriver object - * @param[in] interval new cycle time in timer ticks - * - * @api - */ -void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval) { - - chDbgCheck(gptp != NULL, "gptChangeInterval"); - - chSysLock(); - chDbgAssert(gptp->state == GPT_CONTINUOUS, - "gptChangeInterval(), #1", "invalid state"); - gptChangeIntervalI(gptp, interval); - chSysUnlock(); -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @api - */ -void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval) { - - chSysLock(); - gptStartContinuousI(gptp, interval); - chSysUnlock(); -} - -/** - * @brief Starts the timer in continuous mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval period in ticks - * - * @iclass - */ -void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) { - - chDbgCheckClassI(); - chDbgCheck(gptp != NULL, "gptStartContinuousI"); - chDbgAssert(gptp->state == GPT_READY, - "gptStartContinuousI(), #1", "invalid state"); - - gptp->state = GPT_CONTINUOUS; - gpt_lld_start_timer(gptp, interval); -} - -/** - * @brief Starts the timer in one shot mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval) { - - chSysLock(); - gptStartOneShotI(gptp, interval); - chSysUnlock(); -} - -/** - * @brief Starts the timer in one shot mode. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { - - chDbgCheckClassI(); - chDbgCheck(gptp != NULL, "gptStartOneShotI"); - chDbgAssert(gptp->state == GPT_READY, - "gptStartOneShotI(), #1", "invalid state"); - - gptp->state = GPT_ONESHOT; - gpt_lld_start_timer(gptp, interval); -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStopTimer(GPTDriver *gptp) { - - chSysLock(); - gptStopTimerI(gptp); - chSysUnlock(); -} - -/** - * @brief Stops the timer. - * - * @param[in] gptp pointer to the @p GPTDriver object - * - * @api - */ -void gptStopTimerI(GPTDriver *gptp) { - - chDbgCheckClassI(); - chDbgCheck(gptp != NULL, "gptStopTimerI"); - chDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) || - (gptp->state == GPT_ONESHOT), - "gptStopTimerI(), #1", "invalid state"); - - gptp->state = GPT_READY; - gpt_lld_stop_timer(gptp); -} - -/** - * @brief Starts the timer in one shot mode and waits for completion. - * @details This function specifically polls the timer waiting for completion - * in order to not have extra delays caused by interrupt servicing, - * this function is only recommended for short delays. - * @note The configured callback is not invoked when using this function. - * - * @param[in] gptp pointer to the @p GPTDriver object - * @param[in] interval time interval in ticks - * - * @api - */ -void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) { - - chDbgAssert(gptp->state == GPT_READY, - "gptPolledDelay(), #1", "invalid state"); - - 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 deleted file mode 100644 index 974a8854b..000000000 --- a/os/hal/src/hal.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file hal.c - * @brief HAL subsystem code. - * - * @addtogroup HAL - * @{ - */ - -#include "ch.h" -#include "hal.h" - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief HAL initialization. - * @details This function invokes the low level initialization code then - * initializes all the drivers enabled in the HAL. Finally the - * board-specific initialization is performed by invoking - * @p boardInit() (usually defined in @p board.c). - * - * @init - */ -void halInit(void) { - - hal_lld_init(); - -#if HAL_USE_TM || defined(__DOXYGEN__) - tmInit(); -#endif -#if HAL_USE_PAL || defined(__DOXYGEN__) - palInit(&pal_default_config); -#endif -#if HAL_USE_ADC || defined(__DOXYGEN__) - adcInit(); -#endif -#if HAL_USE_CAN || defined(__DOXYGEN__) - canInit(); -#endif -#if HAL_USE_EXT || defined(__DOXYGEN__) - extInit(); -#endif -#if HAL_USE_GPT || defined(__DOXYGEN__) - gptInit(); -#endif -#if HAL_USE_I2C || defined(__DOXYGEN__) - i2cInit(); -#endif -#if HAL_USE_ICU || defined(__DOXYGEN__) - icuInit(); -#endif -#if HAL_USE_MAC || defined(__DOXYGEN__) - macInit(); -#endif -#if HAL_USE_PWM || defined(__DOXYGEN__) - pwmInit(); -#endif -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - sdInit(); -#endif -#if HAL_USE_SDC || defined(__DOXYGEN__) - sdcInit(); -#endif -#if HAL_USE_SPI || defined(__DOXYGEN__) - spiInit(); -#endif -#if HAL_USE_UART || defined(__DOXYGEN__) - uartInit(); -#endif -#if HAL_USE_USB || defined(__DOXYGEN__) - usbInit(); -#endif -#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) - mmcInit(); -#endif -#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) - sduInit(); -#endif -#if HAL_USE_RTC || defined(__DOXYGEN__) - rtcInit(); -#endif - /* Board specific initialization.*/ - boardInit(); -} - -#if HAL_IMPLEMENTS_COUNTERS || defined(__DOXYGEN__) -/** - * @brief Realtime window test. - * @details This function verifies if the current realtime counter value - * lies within the specified range or not. The test takes care - * of the realtime counter wrapping to zero on overflow. - * @note When start==end then the function returns always true because the - * whole time range is specified. - * @note This is an optional service that could not be implemented in - * all HAL implementations. - * @note This function can be called from any context. - * - * @par Example 1 - * Example of a guarded loop using the realtime counter. The loop implements - * a timeout after one second. - * @code - * halrtcnt_t start = halGetCounterValue(); - * halrtcnt_t timeout = start + S2RTT(1); - * while (my_condition) { - * if (!halIsCounterWithin(start, timeout) - * return TIMEOUT; - * // Do something. - * } - * // Continue. - * @endcode - * - * @par Example 2 - * Example of a loop that lasts exactly 50 microseconds. - * @code - * halrtcnt_t start = halGetCounterValue(); - * halrtcnt_t timeout = start + US2RTT(50); - * while (halIsCounterWithin(start, timeout)) { - * // Do something. - * } - * // Continue. - * @endcode - * - * @param[in] start the start of the time window (inclusive) - * @param[in] end the end of the time window (non inclusive) - * @retval TRUE current time within the specified time window. - * @retval FALSE current time not within the specified time window. - * - * @special - */ -bool_t halIsCounterWithin(halrtcnt_t start, halrtcnt_t end) { - halrtcnt_t now = halGetCounterValue(); - - return end > start ? (now >= start) && (now < end) : - (now >= start) || (now < end); -} - -/** - * @brief Polled delay. - * @note The real delays is always few cycles in excess of the specified - * value. - * @note This is an optional service that could not be implemented in - * all HAL implementations. - * @note This function can be called from any context. - * - * @param[in] ticks number of ticks - * - * @special - */ -void halPolledDelay(halrtcnt_t ticks) { - halrtcnt_t start = halGetCounterValue(); - halrtcnt_t timeout = start + (ticks); - while (halIsCounterWithin(start, timeout)) - ; -} -#endif /* HAL_IMPLEMENTS_COUNTERS */ - -/** @} */ diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c deleted file mode 100644 index 8604488e5..000000000 --- a/os/hal/src/i2c.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file i2c.c - * @brief I2C Driver code. - * - * @addtogroup I2C - * @{ - */ -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2C Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2cInit(void) { - i2c_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2CDriver structure. - * - * @param[out] i2cp pointer to the @p I2CDriver object - * - * @init - */ -void i2cObjectInit(I2CDriver *i2cp) { - - i2cp->state = I2C_STOP; - i2cp->config = NULL; - -#if I2C_USE_MUTUAL_EXCLUSION -#if CH_CFG_USE_MUTEXES - chMtxInit(&i2cp->mutex); -#else - chSemInit(&i2cp->semaphore, 1); -#endif /* CH_CFG_USE_MUTEXES */ -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#if defined(I2C_DRIVER_EXT_INIT_HOOK) - I2C_DRIVER_EXT_INIT_HOOK(i2cp); -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] config pointer to the @p I2CConfig object - * - * @api - */ -void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { - - chDbgCheck((i2cp != NULL) && (config != NULL), "i2cStart"); - chDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), - "i2cStart(), #1", - "invalid state"); - - chSysLock(); - i2cp->config = config; - i2c_lld_start(i2cp); - i2cp->state = I2C_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cStop(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cStop"); - chDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), - "i2cStop(), #1", - "invalid state"); - - chSysLock(); - i2c_lld_stop(i2cp); - i2cp->state = I2C_STOP; - chSysUnlock(); -} - -/** - * @brief Returns the errors mask associated to the previous operation. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @return The errors mask. - * - * @api - */ -i2cflags_t i2cGetErrors(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cGetErrors"); - - return i2c_lld_get_errors(i2cp); -} - -/** - * @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] 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[out] 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] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval RDY_OK if the function succeeded. - * @retval RDY_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval RDY_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, - i2caddr_t addr, - const uint8_t *txbuf, - size_t txbytes, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout) { - msg_t rdymsg; - - chDbgCheck((i2cp != NULL) && (addr != 0) && - (txbytes > 0) && (txbuf != NULL) && - ((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL))) && - (timeout != TIME_IMMEDIATE), - "i2cMasterTransmitTimeout"); - - chDbgAssert(i2cp->state == I2C_READY, - "i2cMasterTransmitTimeout(), #1", "not ready"); - - chSysLock(); - i2cp->errors = I2CD_NO_ERROR; - i2cp->state = I2C_ACTIVE_TX; - rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, - rxbuf, rxbytes, timeout); - if (rdymsg == RDY_TIMEOUT) - i2cp->state = I2C_LOCKED; - else - i2cp->state = I2C_READY; - chSysUnlock(); - return rdymsg; -} - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address (7 bits) without R/W bit - * @param[out] rxbuf pointer to receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval RDY_OK if the function succeeded. - * @retval RDY_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval RDY_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, - i2caddr_t addr, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout){ - - msg_t rdymsg; - - chDbgCheck((i2cp != NULL) && (addr != 0) && - (rxbytes > 0) && (rxbuf != NULL) && - (timeout != TIME_IMMEDIATE), - "i2cMasterReceiveTimeout"); - - chDbgAssert(i2cp->state == I2C_READY, - "i2cMasterReceive(), #1", "not ready"); - - chSysLock(); - i2cp->errors = I2CD_NO_ERROR; - i2cp->state = I2C_ACTIVE_RX; - rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); - if (rdymsg == RDY_TIMEOUT) - i2cp->state = I2C_LOCKED; - else - i2cp->state = I2C_READY; - chSysUnlock(); - return rdymsg; -} - -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the SPI bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cAcquireBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cAcquireBus"); - -#if CH_CFG_USE_MUTEXES - chMtxLock(&i2cp->mutex); -#elif CH_CFG_USE_SEMAPHORES - chSemWait(&i2cp->semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the I2C bus. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cReleaseBus(I2CDriver *i2cp) { - - chDbgCheck(i2cp != NULL, "i2cReleaseBus"); - -#if CH_CFG_USE_MUTEXES - chMtxUnlock(); -#elif CH_CFG_USE_SEMAPHORES - chSemSignal(&i2cp->semaphore); -#endif -} -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#endif /* HAL_USE_I2C */ - -/** @} */ diff --git a/os/hal/src/i2s.c b/os/hal/src/i2s.c deleted file mode 100644 index e43d51ab2..000000000 --- a/os/hal/src/i2s.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file i2s.c - * @brief I2S Driver code. - * - * @addtogroup I2S - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_I2S || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2S Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2sInit(void) { - - i2s_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2SDriver structure. - * - * @param[out] i2sp pointer to the @p I2SDriver object - * - * @init - */ -void i2sObjectInit(I2SDriver *i2sp) { - - i2sp->state = I2S_STOP; - i2sp->config = NULL; -} - -/** - * @brief Configures and activates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * @param[in] config pointer to the @p I2SConfig object - * - * @api - */ -void i2sStart(I2SDriver *i2sp, const I2SConfig *config) { - - chDbgCheck((i2sp != NULL) && (config != NULL), "i2sStart"); - - chSysLock(); - chDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), - "i2sStart(), #1", "invalid state"); - i2sp->config = config; - i2s_lld_start(i2sp); - i2sp->state = I2S_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the I2S peripheral. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStop(I2SDriver *i2sp) { - - chDbgCheck(i2sp != NULL, "i2sStop"); - - chSysLock(); - chDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), - "i2sStop(), #1", "invalid state"); - i2s_lld_stop(i2sp); - i2sp->state = I2S_STOP; - chSysUnlock(); -} - -/** - * @brief Starts a I2S data exchange. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStartExchange(I2SDriver *i2sp) { - - chDbgCheck(i2sp != NULL "i2sStartExchange"); - - chSysLock(); - chDbgAssert(i2sp->state == I2S_READY, - "i2sStartExchange(), #1", "not ready"); - i2sStartExchangeI(i2sp); - chSysUnlock(); -} - -/** - * @brief Starts a I2S data exchange in continuous mode. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStartExchangeContinuous(I2SDriver *i2sp) { - - chDbgCheck(i2sp != NULL "i2sStartExchangeContinuous"); - - chSysLock(); - chDbgAssert(i2sp->state == I2S_READY, - "i2sStartExchangeContinuous(), #1", "not ready"); - i2sStartExchangeContinuousI(i2sp); - chSysUnlock(); -} - -/** - * @brief Stops the ongoing data exchange. - * @details The ongoing data exchange, if any, is stopped, if the driver - * was not active the function does nothing. - * - * @param[in] i2sp pointer to the @p I2SDriver object - * - * @api - */ -void i2sStopExchange(I2SDriver *i2sp) { - - chDbgCheck((i2sp != NULL), "i2sStopExchange"); - - chSysLock(); - chDbgAssert((i2sp->state == I2S_READY) || - (i2sp->state == I2S_ACTIVE) || - (i2sp->state == I2S_COMPLETE), - "i2sStopExchange(), #1", "not ready"); - i2sStopExchangeI(i2sp); - chSysUnlock(); -} - -#endif /* HAL_USE_I2S */ - -/** @} */ diff --git a/os/hal/src/icu.c b/os/hal/src/icu.c deleted file mode 100644 index 65d5de907..000000000 --- a/os/hal/src/icu.c +++ /dev/null @@ -1,159 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file icu.c - * @brief ICU Driver code. - * - * @addtogroup ICU - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_ICU || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief ICU Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void icuInit(void) { - - icu_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p ICUDriver structure. - * - * @param[out] icup pointer to the @p ICUDriver object - * - * @init - */ -void icuObjectInit(ICUDriver *icup) { - - icup->state = ICU_STOP; - icup->config = NULL; -} - -/** - * @brief Configures and activates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * @param[in] config pointer to the @p ICUConfig object - * - * @api - */ -void icuStart(ICUDriver *icup, const ICUConfig *config) { - - chDbgCheck((icup != NULL) && (config != NULL), "icuStart"); - - chSysLock(); - chDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "icuStart(), #1", "invalid state"); - icup->config = config; - icu_lld_start(icup); - icup->state = ICU_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the ICU peripheral. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuStop(ICUDriver *icup) { - - chDbgCheck(icup != NULL, "icuStop"); - - chSysLock(); - chDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "icuStop(), #1", "invalid state"); - icu_lld_stop(icup); - icup->state = ICU_STOP; - chSysUnlock(); -} - -/** - * @brief Enables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuEnable(ICUDriver *icup) { - - chDbgCheck(icup != NULL, "icuEnable"); - - chSysLock(); - chDbgAssert(icup->state == ICU_READY, "icuEnable(), #1", "invalid state"); - icu_lld_enable(icup); - icup->state = ICU_WAITING; - chSysUnlock(); -} - -/** - * @brief Disables the input capture. - * - * @param[in] icup pointer to the @p ICUDriver object - * - * @api - */ -void icuDisable(ICUDriver *icup) { - - chDbgCheck(icup != NULL, "icuDisable"); - - chSysLock(); - chDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) || - (icup->state == ICU_ACTIVE) || (icup->state == ICU_IDLE), - "icuDisable(), #1", "invalid state"); - icu_lld_disable(icup); - icup->state = ICU_READY; - chSysUnlock(); -} - -#endif /* HAL_USE_ICU */ - -/** @} */ diff --git a/os/hal/src/mac.c b/os/hal/src/mac.c deleted file mode 100644 index cb62db612..000000000 --- a/os/hal/src/mac.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file mac.c - * @brief MAC Driver code. - * - * @addtogroup MAC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_MAC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if MAC_USE_ZERO_COPY && !MAC_SUPPORTS_ZERO_COPY -#error "MAC_USE_ZERO_COPY not supported by this implementation" -#endif - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief MAC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void macInit(void) { - - mac_lld_init(); -} - -/** - * @brief Initialize the standard part of a @p MACDriver structure. - * - * @param[out] macp pointer to the @p MACDriver object - * - * @init - */ -void macObjectInit(MACDriver *macp) { - - macp->state = MAC_STOP; - macp->config = NULL; - chSemInit(&macp->tdsem, 0); - chSemInit(&macp->rdsem, 0); -#if MAC_USE_EVENTS - chEvtInit(&macp->rdevent); -#endif -} - -/** - * @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 - * - * @api - */ -void macStop(MACDriver *macp) { - - chDbgCheck(macp != NULL, "macStop"); - - chSysLock(); - chDbgAssert((macp->state == MAC_STOP) || (macp->state == MAC_ACTIVE), - "macStop(), #1", "invalid state"); - mac_lld_stop(macp); - macp->state = MAC_STOP; - chSysUnlock(); -} - -/** - * @brief Allocates a transmission descriptor. - * @details One of the available transmission descriptors is locked and - * returned. If a descriptor is not currently available then the - * invoking thread is queued until one is freed. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] time the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval RDY_OK the descriptor was obtained. - * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. - * - * @api - */ -msg_t macWaitTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp, - systime_t time) { - msg_t msg; - systime_t now; - - chDbgCheck((macp != NULL) && (tdp != NULL), "macWaitTransmitDescriptor"); - chDbgAssert(macp->state == MAC_ACTIVE, "macWaitTransmitDescriptor(), #1", - "not active"); - - while (((msg = mac_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) && - (time > 0)) { - chSysLock(); - now = chTimeNow(); - if ((msg = chSemWaitTimeoutS(&macp->tdsem, time)) == RDY_TIMEOUT) { - chSysUnlock(); - break; - } - if (time != TIME_INFINITE) - time -= (chTimeNow() - now); - chSysUnlock(); - } - return msg; -} - -/** - * @brief Releases a transmit descriptor and starts the transmission of the - * enqueued data as a single frame. - * - * @param[in] tdp the pointer to the @p MACTransmitDescriptor structure - * - * @api - */ -void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { - - chDbgCheck((tdp != NULL), "macReleaseTransmitDescriptor"); - - mac_lld_release_transmit_descriptor(tdp); -} - -/** - * @brief Waits for a received frame. - * @details Stops until a frame is received and buffered. If a frame is - * not immediately available then the invoking thread is queued - * until one is received. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[out] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] time the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_IMMEDIATE immediate timeout. - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval RDY_OK the descriptor was obtained. - * @retval RDY_TIMEOUT the operation timed out, descriptor not initialized. - * - * @api - */ -msg_t macWaitReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp, - systime_t time) { - msg_t msg; - systime_t now; - - chDbgCheck((macp != NULL) && (rdp != NULL), "macWaitReceiveDescriptor"); - chDbgAssert(macp->state == MAC_ACTIVE, "macWaitReceiveDescriptor(), #1", - "not active"); - - while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) && - (time > 0)) { - chSysLock(); - now = chTimeNow(); - if ((msg = chSemWaitTimeoutS(&macp->rdsem, time)) == RDY_TIMEOUT) { - chSysUnlock(); - break; - } - if (time != TIME_INFINITE) - time -= (chTimeNow() - now); - chSysUnlock(); - } - return msg; -} - -/** - * @brief Releases a receive descriptor. - * @details The descriptor and its buffer are made available for more incoming - * frames. - * - * @param[in] rdp the pointer to the @p MACReceiveDescriptor structure - * - * @api - */ -void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { - - chDbgCheck((rdp != NULL), "macReleaseReceiveDescriptor"); - - mac_lld_release_receive_descriptor(rdp); -} - -/** - * @brief Updates and returns the link status. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The link status. - * @retval TRUE if the link is active. - * @retval FALSE if the link is down. - * - * @api - */ -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); -} - -#endif /* HAL_USE_MAC */ - -/** @} */ diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c deleted file mode 100644 index 3a5958ec8..000000000 --- a/os/hal/src/mmc_spi.c +++ /dev/null @@ -1,878 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/* - Parts of this file have been contributed by Matthias Blaicher. - */ - -/** - * @file mmc_spi.c - * @brief MMC over SPI driver code. - * - * @addtogroup MMC_SPI - * @{ - */ - -#include - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* Forward declarations required by mmc_vmt.*/ -static bool_t mmc_read(void *instance, uint32_t startblk, - uint8_t *buffer, uint32_t n); -static bool_t mmc_write(void *instance, uint32_t startblk, - const uint8_t *buffer, uint32_t n); - -/** - * @brief Virtual methods table. - */ -static const struct MMCDriverVMT mmc_vmt = { - (bool_t (*)(void *))mmc_lld_is_card_inserted, - (bool_t (*)(void *))mmc_lld_is_write_protected, - (bool_t (*)(void *))mmcConnect, - (bool_t (*)(void *))mmcDisconnect, - mmc_read, - mmc_write, - (bool_t (*)(void *))mmcSync, - (bool_t (*)(void *, BlockDeviceInfo *))mmcGetInfo -}; - -/** - * @brief Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1). - */ -static const uint8_t crc7_lookup_table[256] = { - 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, - 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, - 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29, - 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, - 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, - 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, - 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66, - 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, - 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, - 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, - 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a, - 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, - 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, - 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, - 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71, - 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, - 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, - 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, - 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c, - 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, - 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, - 0x62, 0x6b, 0x70, 0x79 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -static bool_t mmc_read(void *instance, uint32_t startblk, - uint8_t *buffer, uint32_t n) { - - if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) - return CH_FAILED; - while (n > 0) { - if (mmcSequentialRead((MMCDriver *)instance, buffer)) - return CH_FAILED; - buffer += MMCSD_BLOCK_SIZE; - n--; - } - if (mmcStopSequentialRead((MMCDriver *)instance)) - return CH_FAILED; - return CH_SUCCESS; -} - -static bool_t mmc_write(void *instance, uint32_t startblk, - const uint8_t *buffer, uint32_t n) { - - if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) - return CH_FAILED; - while (n > 0) { - if (mmcSequentialWrite((MMCDriver *)instance, buffer)) - return CH_FAILED; - buffer += MMCSD_BLOCK_SIZE; - n--; - } - if (mmcStopSequentialWrite((MMCDriver *)instance)) - return CH_FAILED; - return CH_SUCCESS; -} - -/** - * @brief Calculate the MMC standard CRC-7 based on a lookup table. - * - * @param[in] crc start value for CRC - * @param[in] buffer pointer to data buffer - * @param[in] len length of data - * @return Calculated CRC - */ -static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) { - - while (len--) - crc = crc7_lookup_table[(crc << 1) ^ (*buffer++)]; - return crc; -} - -/** - * @brief Waits an idle condition. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @notapi - */ -static void wait(MMCDriver *mmcp) { - int i; - uint8_t buf[4]; - - for (i = 0; i < 16; i++) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFF) - return; - } - /* Looks like it is a long wait.*/ - while (TRUE) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFF) - break; -#ifdef MMC_NICE_WAITING - /* Trying to be nice with the other threads.*/ - chThdSleep(1); -#endif - } -} - -/** - * @brief Sends a command header. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * - * @notapi - */ -static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { - uint8_t buf[6]; - - /* Wait for the bus to become idle if a write operation was in progress.*/ - wait(mmcp); - - buf[0] = 0x40 | cmd; - buf[1] = arg >> 24; - buf[2] = arg >> 16; - buf[3] = arg >> 8; - buf[4] = arg; - /* Calculate CRC for command header, shift to right position, add stop bit.*/ - buf[5] = ((crc7(0, buf, 5) & 0x7F) << 1) | 0x01; - - spiSend(mmcp->config->spip, 6, buf); -} - -/** - * @brief Receives a single byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The response as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t recvr1(MMCDriver *mmcp) { - int i; - uint8_t r1[1]; - - for (i = 0; i < 9; i++) { - spiReceive(mmcp->config->spip, 1, r1); - if (r1[0] != 0xFF) - return r1[0]; - } - return 0xFF; -} - -/** - * @brief Receives a three byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to four bytes wide buffer - * @return First response byte as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t recvr3(MMCDriver *mmcp, uint8_t* buffer) { - uint8_t r1; - - r1 = recvr1(mmcp); - spiReceive(mmcp->config->spip, 4, buffer); - - return r1; -} - -/** - * @brief Sends a command an returns a single byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * @return The response as an @p uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { - uint8_t r1; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, arg); - r1 = recvr1(mmcp); - spiUnselect(mmcp->config->spip); - return r1; -} - -/** - * @brief Sends a command which returns a five bytes response (R3). - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] cmd the command id - * @param[in] arg the command argument - * @param[out] response pointer to four bytes wide uint8_t buffer - * @return The first byte of the response (R1) as an @p - * uint8_t value. - * @retval 0xFF timed out. - * - * @notapi - */ -static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, - uint8_t *response) { - uint8_t r1; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, arg); - r1 = recvr3(mmcp, response); - spiUnselect(mmcp->config->spip); - return r1; -} - -/** - * @brief Reads the CSD. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] csd pointer to the CSD buffer - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @notapi - */ -static bool_t read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) { - unsigned i; - uint8_t *bp, buf[16]; - - spiSelect(mmcp->config->spip); - send_hdr(mmcp, cmd, 0); - if (recvr1(mmcp) != 0x00) { - spiUnselect(mmcp->config->spip); - return CH_FAILED; - } - - /* Wait for data availability.*/ - for (i = 0; i < MMC_WAIT_DATA; i++) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFE) { - uint32_t *wp; - - spiReceive(mmcp->config->spip, 16, buf); - bp = buf; - for (wp = &cxd[3]; wp >= cxd; wp--) { - *wp = ((uint32_t)bp[0] << 24) | ((uint32_t)bp[1] << 16) | - ((uint32_t)bp[2] << 8) | (uint32_t)bp[3]; - bp += 4; - } - - /* CRC ignored then end of transaction. */ - spiIgnore(mmcp->config->spip, 2); - spiUnselect(mmcp->config->spip); - - return CH_SUCCESS; - } - } - return CH_FAILED; -} - -/** - * @brief Waits that the card reaches an idle state. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @notapi - */ -static void sync(MMCDriver *mmcp) { - uint8_t buf[1]; - - spiSelect(mmcp->config->spip); - while (TRUE) { - spiReceive(mmcp->config->spip, 1, buf); - if (buf[0] == 0xFF) - break; -#ifdef MMC_NICE_WAITING - chThdSleep(1); /* Trying to be nice with the other threads.*/ -#endif - } - spiUnselect(mmcp->config->spip); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief MMC over SPI driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void mmcInit(void) { - -} - -/** - * @brief Initializes an instance. - * - * @param[out] mmcp pointer to the @p MMCDriver object - * - * @init - */ -void mmcObjectInit(MMCDriver *mmcp) { - - mmcp->vmt = &mmc_vmt; - mmcp->state = BLK_STOP; - mmcp->config = NULL; - mmcp->block_addresses = FALSE; -} - -/** - * @brief Configures and activates the MMC peripheral. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] config pointer to the @p MMCConfig object. - * - * @api - */ -void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { - - chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart"); - chDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), - "mmcStart(), #1", "invalid state"); - - mmcp->config = config; - mmcp->state = BLK_ACTIVE; -} - -/** - * @brief Disables the MMC peripheral. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @api - */ -void mmcStop(MMCDriver *mmcp) { - - chDbgCheck(mmcp != NULL, "mmcStop"); - chDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), - "mmcStop(), #1", "invalid state"); - - spiStop(mmcp->config->spip); - mmcp->state = BLK_STOP; -} - -/** - * @brief Performs the initialization procedure on the inserted card. - * @details This function should be invoked when a card is inserted and - * brings the driver in the @p MMC_READY state where it is possible - * to perform read and write operations. - * @note It is possible to invoke this function from the insertion event - * handler. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded and the driver is now - * in the @p MMC_READY state. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcConnect(MMCDriver *mmcp) { - unsigned i; - uint8_t r3[4]; - - chDbgCheck(mmcp != NULL, "mmcConnect"); - - chDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), - "mmcConnect(), #1", "invalid state"); - - /* Connection procedure in progress.*/ - mmcp->state = BLK_CONNECTING; - - /* Slow clock mode and 128 clock pulses.*/ - spiStart(mmcp->config->spip, mmcp->config->lscfg); - spiIgnore(mmcp->config->spip, 16); - - /* SPI mode selection.*/ - i = 0; - while (TRUE) { - if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01) - break; - if (++i >= MMC_CMD0_RETRY) - goto failed; - chThdSleepMilliseconds(10); - } - - /* Try to detect if this is a high capacity card and switch to block - addresses if possible. - This method is based on "How to support SDC Ver2 and high capacity cards" - by ElmChan.*/ - if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND, - MMCSD_CMD8_PATTERN, r3) != 0x05) { - - /* Switch to SDHC mode.*/ - i = 0; - while (TRUE) { - if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01) && - (send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, - 0x400001aa, r3) == 0x00)) - break; - - if (++i >= MMC_ACMD41_RETRY) - goto failed; - chThdSleepMilliseconds(10); - } - - /* Execute dedicated read on OCR register */ - send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3); - - /* Check if CCS is set in response. Card operates in block mode if set.*/ - if (r3[0] & 0x40) - mmcp->block_addresses = TRUE; - } - - /* Initialization.*/ - i = 0; - while (TRUE) { - uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0); - if (b == 0x00) - break; - if (b != 0x01) - goto failed; - if (++i >= MMC_CMD1_RETRY) - goto failed; - chThdSleepMilliseconds(10); - } - - /* Initialization complete, full speed.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - - /* Setting block size.*/ - if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN, - MMCSD_BLOCK_SIZE) != 0x00) - goto failed; - - /* Determine capacity.*/ - if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) - goto failed; - mmcp->capacity = mmcsdGetCapacity(mmcp->csd); - if (mmcp->capacity == 0) - goto failed; - - if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) - goto failed; - - mmcp->state = BLK_READY; - return CH_SUCCESS; - - /* Connection failed, state reset to BLK_ACTIVE.*/ -failed: - spiStop(mmcp->config->spip); - mmcp->state = BLK_ACTIVE; - return CH_FAILED; -} - -/** - * @brief Brings the driver in a state safe for card removal. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @return The operation status. - * - * @retval CH_SUCCESS the operation succeeded and the driver is now - * in the @p MMC_INSERTED state. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcDisconnect(MMCDriver *mmcp) { - - chDbgCheck(mmcp != NULL, "mmcDisconnect"); - - chSysLock(); - chDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), - "mmcDisconnect(), #1", "invalid state"); - if (mmcp->state == BLK_ACTIVE) { - chSysUnlock(); - return CH_SUCCESS; - } - mmcp->state = BLK_DISCONNECTING; - chSysUnlock(); - - /* Wait for the pending write operations to complete.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - sync(mmcp); - - spiStop(mmcp->config->spip); - mmcp->state = BLK_ACTIVE; - return CH_SUCCESS; -} - -/** - * @brief Starts a sequential read. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk first block to read - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { - - chDbgCheck(mmcp != NULL, "mmcStartSequentialRead"); - chDbgAssert(mmcp->state == BLK_READY, - "mmcStartSequentialRead(), #1", "invalid state"); - - /* Read operation in progress.*/ - mmcp->state = BLK_READING; - - /* (Re)starting the SPI in case it has been reprogrammed externally, it can - happen if the SPI bus is shared among multiple peripherals.*/ - spiStart(mmcp->config->spip, mmcp->config->hscfg); - spiSelect(mmcp->config->spip); - - if (mmcp->block_addresses) - send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk); - else - send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE); - - if (recvr1(mmcp) != 0x00) { - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_FAILED; - } - return CH_SUCCESS; -} - -/** - * @brief Reads a block within a sequential read operation. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to the read buffer - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { - int i; - - chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); - - if (mmcp->state != BLK_READING) - return CH_FAILED; - - for (i = 0; i < MMC_WAIT_DATA; i++) { - spiReceive(mmcp->config->spip, 1, buffer); - if (buffer[0] == 0xFE) { - spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer); - /* CRC ignored. */ - spiIgnore(mmcp->config->spip, 2); - return CH_SUCCESS; - } - } - /* Timeout.*/ - spiUnselect(mmcp->config->spip); - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_FAILED; -} - -/** - * @brief Stops a sequential read gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcStopSequentialRead(MMCDriver *mmcp) { - static const uint8_t stopcmd[] = {0x40 | MMCSD_CMD_STOP_TRANSMISSION, - 0, 0, 0, 0, 1, 0xFF}; - - chDbgCheck(mmcp != NULL, "mmcStopSequentialRead"); - - if (mmcp->state != BLK_READING) - return CH_FAILED; - - spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd); -/* result = recvr1(mmcp) != 0x00;*/ - /* Note, ignored r1 response, it can be not zero, unknown issue.*/ - (void) recvr1(mmcp); - - /* Read operation finished.*/ - spiUnselect(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_SUCCESS; -} - -/** - * @brief Starts a sequential write. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk first block to write - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { - - chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite"); - chDbgAssert(mmcp->state == BLK_READY, - "mmcStartSequentialWrite(), #1", "invalid state"); - - /* Write operation in progress.*/ - mmcp->state = BLK_WRITING; - - spiStart(mmcp->config->spip, mmcp->config->hscfg); - spiSelect(mmcp->config->spip); - if (mmcp->block_addresses) - send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk); - else - send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, - startblk * MMCSD_BLOCK_SIZE); - - if (recvr1(mmcp) != 0x00) { - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_FAILED; - } - return CH_SUCCESS; -} - -/** - * @brief Writes a block within a sequential write operation. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] buffer pointer to the write buffer - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { - static const uint8_t start[] = {0xFF, 0xFC}; - uint8_t b[1]; - - chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialWrite"); - - if (mmcp->state != BLK_WRITING) - return CH_FAILED; - - spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ - spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ - spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ - spiReceive(mmcp->config->spip, 1, b); - if ((b[0] & 0x1F) == 0x05) { - wait(mmcp); - return CH_SUCCESS; - } - - /* Error.*/ - spiUnselect(mmcp->config->spip); - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_FAILED; -} - -/** - * @brief Stops a sequential write gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcStopSequentialWrite(MMCDriver *mmcp) { - static const uint8_t stop[] = {0xFD, 0xFF}; - - chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite"); - - if (mmcp->state != BLK_WRITING) - return CH_FAILED; - - spiSend(mmcp->config->spip, sizeof(stop), stop); - spiUnselect(mmcp->config->spip); - - /* Write operation finished.*/ - mmcp->state = BLK_READY; - return CH_SUCCESS; -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcSync(MMCDriver *mmcp) { - - chDbgCheck(mmcp != NULL, "mmcSync"); - - if (mmcp->state != BLK_READY) - return CH_FAILED; - - /* Synchronization operation in progress.*/ - mmcp->state = BLK_SYNCING; - - spiStart(mmcp->config->spip, mmcp->config->hscfg); - sync(mmcp); - - /* Synchronization operation finished.*/ - mmcp->state = BLK_READY; - return CH_SUCCESS; -} - -/** - * @brief Returns the media info. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[out] bdip pointer to a @p BlockDeviceInfo structure - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { - - chDbgCheck((mmcp != NULL) && (bdip != NULL), "mmcGetInfo"); - - if (mmcp->state != BLK_READY) - return CH_FAILED; - - bdip->blk_num = mmcp->capacity; - bdip->blk_size = MMCSD_BLOCK_SIZE; - - return CH_SUCCESS; -} - -/** - * @brief Erases blocks. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] startblk starting block number - * @param[in] endblk ending block number - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) { - - chDbgCheck((mmcp != NULL), "mmcErase"); - - /* Erase operation in progress.*/ - mmcp->state = BLK_WRITING; - - /* Handling command differences between HC and normal cards.*/ - if (!mmcp->block_addresses) { - startblk *= MMCSD_BLOCK_SIZE; - endblk *= MMCSD_BLOCK_SIZE; - } - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk)) - goto failed; - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk)) - goto failed; - - if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0)) - goto failed; - - mmcp->state = BLK_READY; - return CH_SUCCESS; - - /* Command failed, state reset to BLK_ACTIVE.*/ -failed: - spiStop(mmcp->config->spip); - mmcp->state = BLK_READY; - return CH_FAILED; -} - -#endif /* HAL_USE_MMC_SPI */ - -/** @} */ diff --git a/os/hal/src/mmcsd.c b/os/hal/src/mmcsd.c deleted file mode 100644 index c83095981..000000000 --- a/os/hal/src/mmcsd.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file mmcsd.c - * @brief MMC/SD cards common code. - * - * @addtogroup MMCSD - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_MMC_SPI || HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Gets a bit field from a words array. - * @note The bit zero is the LSb of the first word. - * - * @param[in] data pointer to the words array - * @param[in] end bit offset of the last bit of the field, inclusive - * @param[in] start bit offset of the first bit of the field, inclusive - * - * @return The bits field value, left aligned. - * - * @notapi - */ -static uint32_t mmcsd_get_slice(uint32_t *data, uint32_t end, uint32_t start) { - unsigned startidx, endidx, startoff; - uint32_t endmask; - - chDbgCheck((end >= start) && ((end - start) < 32), "mmcsd_get_slice"); - - startidx = start / 32; - startoff = start % 32; - endidx = end / 32; - endmask = (1 << ((end % 32) + 1)) - 1; - - /* One or two pieces?*/ - if (startidx < endidx) - return (data[startidx] >> startoff) | /* Two pieces case. */ - ((data[endidx] & endmask) << (32 - startoff)); - return (data[startidx] & endmask) >> startoff; /* One piece case. */ -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Extract card capacity from a CSD. - * @details The capacity is returned as number of available blocks. - * - * @param[in] csd the CSD record - * - * @return The card capacity. - * @retval 0 CSD format error - */ -uint32_t mmcsdGetCapacity(uint32_t csd[4]) { - - switch (csd[3] >> 30) { - uint32_t a, b, c; - case 0: - /* CSD version 1.0 */ - a = mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_SLICE); - b = mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_MULT_SLICE); - c = mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BL_LEN_SLICE); - return (a + 1) << (b + 2) << (c - 9); /* 2^9 == MMCSD_BLOCK_SIZE. */ - case 1: - /* CSD version 2.0.*/ - return 1024 * (mmcsd_get_slice(csd, MMCSD_CSD_20_C_SIZE_SLICE) + 1); - default: - /* Reserved value detected.*/ - return 0; - } -} - -#endif /* HAL_USE_MMC_SPI || HAL_USE_SDC */ - -/** @} */ diff --git a/os/hal/src/pal.c b/os/hal/src/pal.c deleted file mode 100644 index cc382edab..000000000 --- a/os/hal/src/pal.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file pal.c - * @brief I/O Ports Abstraction Layer code. - * - * @addtogroup PAL - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_PAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Read from an I/O bus. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p chSysLock() and - * @p chSysUnlock(). - * @note The function internally uses the @p palReadGroup() macro. The use - * of this function is preferred when you value code size, readability - * and error checking over speed. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return The bus logical states. - * - * @api - */ -ioportmask_t palReadBus(IOBus *bus) { - - chDbgCheck((bus != NULL) && - (bus->offset < PAL_IOPORTS_WIDTH), "palReadBus"); - - return palReadGroup(bus->portid, bus->mask, bus->offset); -} - -/** - * @brief Write to an I/O bus. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p chSysLock() and - * @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] bits the bits to be written on the I/O bus. Values exceeding - * the bus width are masked so most significant bits are - * lost. - * - * @api - */ -void palWriteBus(IOBus *bus, ioportmask_t bits) { - - chDbgCheck((bus != NULL) && - (bus->offset < PAL_IOPORTS_WIDTH), "palWriteBus"); - - palWriteGroup(bus->portid, bus->mask, bus->offset, bits); -} - -/** - * @brief Programs a bus with the specified mode. - * @note The operation is not guaranteed to be atomic on all the - * architectures, for atomicity and/or portability reasons you may - * need to enclose port I/O operations between @p chSysLock() and - * @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] mode the mode - * - * @api - */ -void palSetBusMode(IOBus *bus, iomode_t mode) { - - chDbgCheck((bus != NULL) && - (bus->offset < PAL_IOPORTS_WIDTH), "palSetBusMode"); - - palSetGroupMode(bus->portid, bus->mask, bus->offset, mode); -} - -#endif /* HAL_USE_PAL */ - -/** @} */ diff --git a/os/hal/src/pwm.c b/os/hal/src/pwm.c deleted file mode 100644 index c6843a928..000000000 --- a/os/hal/src/pwm.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file pwm.c - * @brief PWM Driver code. - * - * @addtogroup PWM - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_PWM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief PWM Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void pwmInit(void) { - - pwm_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p PWMDriver structure. - * - * @param[out] pwmp pointer to a @p PWMDriver object - * - * @init - */ -void pwmObjectInit(PWMDriver *pwmp) { - - pwmp->state = PWM_STOP; - pwmp->config = NULL; -#if defined(PWM_DRIVER_EXT_INIT_HOOK) - PWM_DRIVER_EXT_INIT_HOOK(pwmp); -#endif -} - -/** - * @brief Configures and activates the PWM peripheral. - * @note Starting a driver that is already in the @p PWM_READY state - * disables all the active channels. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] config pointer to a @p PWMConfig object - * - * @api - */ -void pwmStart(PWMDriver *pwmp, const PWMConfig *config) { - - chDbgCheck((pwmp != NULL) && (config != NULL), "pwmStart"); - - chSysLock(); - chDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "pwmStart(), #1", "invalid state"); - pwmp->config = config; - pwmp->period = config->period; - pwm_lld_start(pwmp); - pwmp->state = PWM_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the PWM peripheral. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * - * @api - */ -void pwmStop(PWMDriver *pwmp) { - - chDbgCheck(pwmp != NULL, "pwmStop"); - - chSysLock(); - chDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "pwmStop(), #1", "invalid state"); - pwm_lld_stop(pwmp); - pwmp->state = PWM_STOP; - chSysUnlock(); -} - -/** - * @brief Changes the period the PWM peripheral. - * @details This function changes the period of a PWM unit that has already - * been activated using @p pwmStart(). - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The PWM unit period is changed to the new value. - * @note If a period is specified that is shorter than the pulse width - * programmed in one of the channels then the behavior is not - * guaranteed. - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] period new cycle time in ticks - * - * @api - */ -void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) { - - chDbgCheck(pwmp != NULL, "pwmChangePeriod"); - - chSysLock(); - chDbgAssert(pwmp->state == PWM_READY, - "pwmChangePeriod(), #1", "invalid state"); - pwmChangePeriodI(pwmp, period); - chSysUnlock(); -} - -/** - * @brief Enables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is active using the specified configuration. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * @param[in] width PWM pulse width as clock pulses number - * - * @api - */ -void pwmEnableChannel(PWMDriver *pwmp, - pwmchannel_t channel, - pwmcnt_t width) { - - chDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS), - "pwmEnableChannel"); - - chSysLock(); - chDbgAssert(pwmp->state == PWM_READY, - "pwmEnableChannel(), #1", "not ready"); - pwm_lld_enable_channel(pwmp, channel, width); - chSysUnlock(); -} - -/** - * @brief Disables a PWM channel. - * @pre The PWM unit must have been activated using @p pwmStart(). - * @post The channel is disabled and its output line returned to the - * idle state. - * @note Depending on the hardware implementation this function has - * effect starting on the next cycle (recommended implementation) - * or immediately (fallback implementation). - * - * @param[in] pwmp pointer to a @p PWMDriver object - * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) - * - * @api - */ -void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { - - chDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS), - "pwmEnableChannel"); - - chSysLock(); - chDbgAssert(pwmp->state == PWM_READY, - "pwmDisableChannel(), #1", "not ready"); - pwm_lld_disable_channel(pwmp, channel); - chSysUnlock(); -} - -#endif /* HAL_USE_PWM */ - -/** @} */ diff --git a/os/hal/src/rtc.c b/os/hal/src/rtc.c deleted file mode 100644 index e0a1c227b..000000000 --- a/os/hal/src/rtc.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file rtc.c - * @brief RTC Driver code. - * - * @addtogroup RTC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_RTC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @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) { - - rtc_lld_init(); -} - -/** - * @brief Set current time. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] timespec pointer to a @p RTCTime structure - * - * @api - */ -void rtcSetTime(RTCDriver *rtcp, const RTCTime *timespec) { - - chDbgCheck((rtcp != NULL) && (timespec != NULL), "rtcSetTime"); - - chSysLock(); - rtcSetTimeI(rtcp, timespec); - chSysUnlock(); -} - -/** - * @brief Get current time. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[out] timespec pointer to a @p RTCTime structure - * - * @api - */ -void rtcGetTime(RTCDriver *rtcp, RTCTime *timespec) { - - chDbgCheck((rtcp != NULL) && (timespec != NULL), "rtcGetTime"); - - chSysLock(); - rtcGetTimeI(rtcp, timespec); - chSysUnlock(); -} - -#if (RTC_ALARMS > 0) || defined(__DOXYGEN__) -/** - * @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 - */ -void rtcSetAlarm(RTCDriver *rtcp, - rtcalarm_t alarm, - const RTCAlarm *alarmspec) { - - chDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS), "rtcSetAlarm"); - - chSysLock(); - rtcSetAlarmI(rtcp, alarm, alarmspec); - chSysUnlock(); -} - -/** - * @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 rtcGetAlarm(RTCDriver *rtcp, - rtcalarm_t alarm, - RTCAlarm *alarmspec) { - - chDbgCheck((rtcp != NULL) && (alarm < RTC_ALARMS) && (alarmspec != NULL), - "rtcGetAlarm"); - - chSysLock(); - rtcGetAlarmI(rtcp, alarm, alarmspec); - chSysUnlock(); -} -#endif /* RTC_ALARMS > 0 */ - -#if RTC_SUPPORTS_CALLBACKS || defined(__DOXYGEN__) -/** - * @brief Enables or disables RTC callbacks. - * @details This function enables or disables the callback, use a @p NULL - * pointer in order to disable it. - * - * @param[in] rtcp pointer to RTC driver structure - * @param[in] callback callback function pointer or @p NULL - * - * @api - */ -void rtcSetCallback(RTCDriver *rtcp, rtccb_t callback) { - - chDbgCheck((rtcp != NULL), "rtcSetCallback"); - - chSysLock(); - rtcSetCallbackI(rtcp, callback); - chSysUnlock(); -} -#endif /* RTC_SUPPORTS_CALLBACKS */ - -/** - * @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 rtcGetTimeFat(RTCDriver *rtcp) { - - chDbgCheck((rtcp != NULL), "rtcSetTime"); - return rtc_lld_get_time_fat(rtcp); -} - -#endif /* HAL_USE_RTC */ - -/** @} */ diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c deleted file mode 100644 index f95331d44..000000000 --- a/os/hal/src/sdc.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file sdc.c - * @brief SDC Driver code. - * - * @addtogroup SDC - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SDC || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Virtual methods table. - */ -static const struct SDCDriverVMT sdc_vmt = { - (bool_t (*)(void *))sdc_lld_is_card_inserted, - (bool_t (*)(void *))sdc_lld_is_write_protected, - (bool_t (*)(void *))sdcConnect, - (bool_t (*)(void *))sdcDisconnect, - (bool_t (*)(void *, uint32_t, uint8_t *, uint32_t))sdcRead, - (bool_t (*)(void *, uint32_t, const uint8_t *, uint32_t))sdcWrite, - (bool_t (*)(void *))sdcSync, - (bool_t (*)(void *, BlockDeviceInfo *))sdcGetInfo -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Wait for the card to complete pending operations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @notapi - */ -bool_t _sdc_wait_for_transfer_state(SDCDriver *sdcp) { - uint32_t resp[1]; - - while (TRUE) { - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_STATUS, - sdcp->rca, resp) || - MMCSD_R1_ERROR(resp[0])) - return CH_FAILED; - switch (MMCSD_R1_STS(resp[0])) { - case MMCSD_STS_TRAN: - return CH_SUCCESS; - case MMCSD_STS_DATA: - case MMCSD_STS_RCV: - case MMCSD_STS_PRG: -#if SDC_NICE_WAITING - chThdSleepMilliseconds(1); -#endif - continue; - default: - /* The card should have been initialized so any other state is not - valid and is reported as an error.*/ - return CH_FAILED; - } - } - /* If something going too wrong.*/ - return CH_FAILED; -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief SDC Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sdcInit(void) { - - sdc_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p SDCDriver structure. - * - * @param[out] sdcp pointer to the @p SDCDriver object - * - * @init - */ -void sdcObjectInit(SDCDriver *sdcp) { - - sdcp->vmt = &sdc_vmt; - sdcp->state = BLK_STOP; - sdcp->errors = SDC_NO_ERROR; - sdcp->config = NULL; - sdcp->capacity = 0; -} - -/** - * @brief Configures and activates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] config pointer to the @p SDCConfig object, can be @p NULL if - * the driver supports a default configuration or - * requires no configuration - * - * @api - */ -void sdcStart(SDCDriver *sdcp, const SDCConfig *config) { - - chDbgCheck(sdcp != NULL, "sdcStart"); - - chSysLock(); - chDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), - "sdcStart(), #1", "invalid state"); - sdcp->config = config; - sdc_lld_start(sdcp); - sdcp->state = BLK_ACTIVE; - chSysUnlock(); -} - -/** - * @brief Deactivates the SDC peripheral. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @api - */ -void sdcStop(SDCDriver *sdcp) { - - chDbgCheck(sdcp != NULL, "sdcStop"); - - chSysLock(); - chDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), - "sdcStop(), #1", "invalid state"); - sdc_lld_stop(sdcp); - sdcp->state = BLK_STOP; - chSysUnlock(); -} - -/** - * @brief Performs the initialization procedure on the inserted card. - * @details This function should be invoked when a card is inserted and - * brings the driver in the @p BLK_READY state where it is possible - * to perform read and write operations. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @api - */ -bool_t sdcConnect(SDCDriver *sdcp) { - uint32_t resp[1]; - - chDbgCheck(sdcp != NULL, "sdcConnect"); - chDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), - "mmcConnect(), #1", "invalid state"); - - /* Connection procedure in progress.*/ - sdcp->state = BLK_CONNECTING; - - /* Card clock initialization.*/ - sdc_lld_start_clk(sdcp); - - /* Enforces the initial card state.*/ - sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); - - /* V2.0 cards detection.*/ - if (!sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_IF_COND, - MMCSD_CMD8_PATTERN, resp)) { - sdcp->cardmode = SDC_MODE_CARDTYPE_SDV20; - /* Voltage verification.*/ - if (((resp[0] >> 8) & 0xF) != 1) - goto failed; - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - } - else { -#if SDC_MMC_SUPPORT - /* MMC or SD V1.1 detection.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) - sdcp->cardmode = SDC_MODE_CARDTYPE_MMC; - else -#endif /* SDC_MMC_SUPPORT */ - sdcp->cardmode = SDC_MODE_CARDTYPE_SDV11; - } - -#if SDC_MMC_SUPPORT - if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) { - /* TODO: MMC initialization.*/ - goto failed; - } - else -#endif /* SDC_MMC_SUPPORT */ - { - unsigned i; - uint32_t ocr; - - /* SD initialization.*/ - if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20) - ocr = 0xC0100000; - else - ocr = 0x80100000; - - /* SD-type initialization. */ - i = 0; - while (TRUE) { - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_APP_OP_COND, ocr, resp)) - goto failed; - if ((resp[0] & 0x80000000) != 0) { - if (resp[0] & 0x40000000) - sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; - break; - } - if (++i >= SDC_INIT_RETRY) - goto failed; - chThdSleepMilliseconds(10); - } - } - - /* Reads CID.*/ - if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_ALL_SEND_CID, 0, sdcp->cid)) - goto failed; - - /* Asks for the RCA.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_RELATIVE_ADDR, - 0, &sdcp->rca)) - goto failed; - - /* Reads CSD.*/ - if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_SEND_CSD, - sdcp->rca, sdcp->csd)) - goto failed; - - /* Switches to high speed.*/ - sdc_lld_set_data_clk(sdcp); - - /* Selects the card for operations.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEL_DESEL_CARD, - sdcp->rca, resp)) - goto failed; - - /* Block length fixed at 512 bytes.*/ - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BLOCKLEN, - MMCSD_BLOCK_SIZE, resp) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - - /* Switches to wide bus mode.*/ - switch (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) { - case SDC_MODE_CARDTYPE_SDV11: - case SDC_MODE_CARDTYPE_SDV20: - sdc_lld_set_bus_mode(sdcp, SDC_MODE_4BIT); - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, sdcp->rca, resp) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BUS_WIDTH, 2, resp) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - break; - } - - /* Determine capacity.*/ - sdcp->capacity = mmcsdGetCapacity(sdcp->csd); - if (sdcp->capacity == 0) - goto failed; - - /* Initialization complete.*/ - sdcp->state = BLK_READY; - return CH_SUCCESS; - - /* Connection failed, state reset to BLK_ACTIVE.*/ -failed: - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return CH_FAILED; -} - -/** - * @brief Brings the driver in a state safe for card removal. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @api - */ -bool_t sdcDisconnect(SDCDriver *sdcp) { - - chDbgCheck(sdcp != NULL, "sdcDisconnect"); - - chSysLock(); - chDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), - "sdcDisconnect(), #1", "invalid state"); - if (sdcp->state == BLK_ACTIVE) { - chSysUnlock(); - return CH_SUCCESS; - } - sdcp->state = BLK_DISCONNECTING; - chSysUnlock(); - - /* Waits for eventual pending operations completion.*/ - if (_sdc_wait_for_transfer_state(sdcp)) { - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return CH_FAILED; - } - - /* Card clock stopped.*/ - sdc_lld_stop_clk(sdcp); - sdcp->state = BLK_ACTIVE; - return CH_SUCCESS; -} - -/** - * @brief Reads one or more blocks. - * @pre The driver must be in the @p BLK_READY state after a successful - * sdcConnect() invocation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to read - * @param[out] buf pointer to the read buffer - * @param[in] n number of blocks to read - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @api - */ -bool_t sdcRead(SDCDriver *sdcp, uint32_t startblk, - uint8_t *buf, uint32_t n) { - bool_t status; - - chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcRead"); - chDbgAssert(sdcp->state == BLK_READY, "sdcRead(), #1", "invalid state"); - - if ((startblk + n - 1) > sdcp->capacity){ - sdcp->errors |= SDC_OVERFLOW_ERROR; - return CH_FAILED; - } - - /* Read operation in progress.*/ - sdcp->state = BLK_READING; - - status = sdc_lld_read(sdcp, startblk, buf, n); - - /* Read operation finished.*/ - sdcp->state = BLK_READY; - return status; -} - -/** - * @brief Writes one or more blocks. - * @pre The driver must be in the @p BLK_READY state after a successful - * sdcConnect() invocation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk first block to write - * @param[out] buf pointer to the write buffer - * @param[in] n number of blocks to write - * - * @return The operation status. - * @retval CH_SUCCESS operation succeeded. - * @retval CH_FAILED operation failed. - * - * @api - */ -bool_t sdcWrite(SDCDriver *sdcp, uint32_t startblk, - const uint8_t *buf, uint32_t n) { - bool_t status; - - chDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0), "sdcWrite"); - chDbgAssert(sdcp->state == BLK_READY, "sdcWrite(), #1", "invalid state"); - - if ((startblk + n - 1) > sdcp->capacity){ - sdcp->errors |= SDC_OVERFLOW_ERROR; - return CH_FAILED; - } - - /* Write operation in progress.*/ - sdcp->state = BLK_WRITING; - - status = sdc_lld_write(sdcp, startblk, buf, n); - - /* Write operation finished.*/ - sdcp->state = BLK_READY; - return status; -} - -/** - * @brief Returns the errors mask associated to the previous operation. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @return The errors mask. - * - * @api - */ -sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) { - sdcflags_t flags; - - chDbgCheck(sdcp != NULL, "sdcGetAndClearErrors"); - chDbgAssert(sdcp->state == BLK_READY, - "sdcGetAndClearErrors(), #1", "invalid state"); - - chSysLock(); - flags = sdcp->errors; - sdcp->errors = SDC_NO_ERROR; - chSysUnlock(); - return flags; -} - -/** - * @brief Waits for card idle condition. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t sdcSync(SDCDriver *sdcp) { - bool_t result; - - chDbgCheck(sdcp != NULL, "sdcSync"); - - if (sdcp->state != BLK_READY) - return CH_FAILED; - - /* Synchronization operation in progress.*/ - sdcp->state = BLK_SYNCING; - - result = sdc_lld_sync(sdcp); - - /* Synchronization operation finished.*/ - sdcp->state = BLK_READY; - return result; -} - -/** - * @brief Returns the media info. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[out] bdip pointer to a @p BlockDeviceInfo structure - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) { - - chDbgCheck((sdcp != NULL) && (bdip != NULL), "sdcGetInfo"); - - if (sdcp->state != BLK_READY) - return CH_FAILED; - - bdip->blk_num = sdcp->capacity; - bdip->blk_size = MMCSD_BLOCK_SIZE; - - return CH_SUCCESS; -} - - -/** - * @brief Erases the supplied blocks. - * - * @param[in] sdcp pointer to the @p SDCDriver object - * @param[in] startblk starting block number - * @param[in] endblk ending block number - * - * @return The operation status. - * @retval CH_SUCCESS the operation succeeded. - * @retval CH_FAILED the operation failed. - * - * @api - */ -bool_t sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) { - uint32_t resp[1]; - - chDbgCheck((sdcp != NULL), "sdcErase"); - chDbgAssert(sdcp->state == BLK_READY, "sdcErase(), #1", "invalid state"); - - /* Erase operation in progress.*/ - sdcp->state = BLK_WRITING; - - /* Handling command differences between HC and normal cards.*/ - if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) { - startblk *= MMCSD_BLOCK_SIZE; - endblk *= MMCSD_BLOCK_SIZE; - } - - _sdc_wait_for_transfer_state(sdcp); - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START, - startblk, resp) != CH_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END, - endblk, resp) != CH_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - - if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE, - 0, resp) != CH_SUCCESS) || - MMCSD_R1_ERROR(resp[0])) - goto failed; - - /* Quick sleep to allow it to transition to programming or receiving state */ - /* TODO: ??????????????????????????? */ - - /* Wait for it to return to transfer state to indicate it has finished erasing */ - _sdc_wait_for_transfer_state(sdcp); - - sdcp->state = BLK_READY; - return CH_SUCCESS; - -failed: - sdcp->state = BLK_READY; - return CH_FAILED; -} - -#endif /* HAL_USE_SDC */ - -/** @} */ diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c deleted file mode 100644 index ca09e9d64..000000000 --- a/os/hal/src/serial.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file serial.c - * @brief Serial Driver code. - * - * @addtogroup SERIAL - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SERIAL || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/* - * Interface implementation, the following functions just invoke the equivalent - * queue-level function or macro. - */ - -static size_t write(void *ip, const uint8_t *bp, size_t n) { - - return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, - n, TIME_INFINITE); -} - -static size_t read(void *ip, uint8_t *bp, size_t n) { - - return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, - n, TIME_INFINITE); -} - -static msg_t put(void *ip, uint8_t b) { - - return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE); -} - -static msg_t get(void *ip) { - - return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE); -} - -static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - - return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); -} - -static msg_t gett(void *ip, systime_t timeout) { - - return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); -} - -static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { - - return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, time); -} - -static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { - - return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, time); -} - -static const struct SerialDriverVMT vmt = { - write, read, put, get, - putt, gett, writet, readt -}; - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Serial Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sdInit(void) { - - sd_lld_init(); -} - -/** - * @brief Initializes a generic full duplex driver object. - * @details The HW dependent part of the initialization has to be performed - * outside, usually in the hardware initialization code. - * - * @param[out] sdp pointer to a @p SerialDriver structure - * @param[in] inotify pointer to a callback function that is invoked when - * some data is read from the Queue. The value can be - * @p NULL. - * @param[in] onotify pointer to a callback function that is invoked when - * some data is written in the Queue. The value can be - * @p NULL. - * - * @init - */ -void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { - - sdp->vmt = &vmt; - chEvtObjectInit(&sdp->event); - sdp->state = SD_STOP; - chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); - chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); -} - -/** - * @brief Configures and starts the driver. - * - * @param[in] sdp pointer to a @p SerialDriver object - * @param[in] config the architecture-dependent serial driver configuration. - * If this parameter is set to @p NULL then a default - * configuration is used. - * - * @api - */ -void sdStart(SerialDriver *sdp, const SerialConfig *config) { - - chDbgCheck(sdp != NULL, "sdStart"); - - chSysLock(); - chDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "sdStart(), #1", - "invalid state"); - sd_lld_start(sdp, config); - sdp->state = SD_READY; - chSysUnlock(); -} - -/** - * @brief Stops the driver. - * @details Any thread waiting on the driver's queues will be awakened with - * the message @p Q_RESET. - * - * @param[in] sdp pointer to a @p SerialDriver object - * - * @api - */ -void sdStop(SerialDriver *sdp) { - - chDbgCheck(sdp != NULL, "sdStop"); - - chSysLock(); - chDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "sdStop(), #1", - "invalid state"); - sd_lld_stop(sdp); - sdp->state = SD_STOP; - chOQResetI(&sdp->oqueue); - chIQResetI(&sdp->iqueue); - chSchRescheduleS(); - chSysUnlock(); -} - -/** - * @brief Handles incoming data. - * @details This function must be called from the input interrupt service - * routine in order to enqueue incoming data and generate the - * related events. - * @note The incoming data event is only generated when the input queue - * becomes non-empty. - * @note In order to gain some performance it is suggested to not use - * this function directly but copy this code directly into the - * interrupt service routine. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @param[in] b the byte to be written in the driver's Input Queue - * - * @iclass - */ -void sdIncomingDataI(SerialDriver *sdp, uint8_t b) { - - chDbgCheckClassI(); - chDbgCheck(sdp != NULL, "sdIncomingDataI"); - - if (chIQIsEmptyI(&sdp->iqueue)) - chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); - if (chIQPutI(&sdp->iqueue, b) < Q_OK) - chnAddFlagsI(sdp, SD_OVERRUN_ERROR); -} - -/** - * @brief Handles outgoing data. - * @details Must be called from the output interrupt service routine in order - * to get the next byte to be transmitted. - * @note In order to gain some performance it is suggested to not use - * this function directly but copy this code directly into the - * interrupt service routine. - * - * @param[in] sdp pointer to a @p SerialDriver structure - * @return The byte value read from the driver's output queue. - * @retval Q_EMPTY if the queue is empty (the lower driver usually - * disables the interrupt source when this happens). - * - * @iclass - */ -msg_t sdRequestDataI(SerialDriver *sdp) { - msg_t b; - - chDbgCheckClassI(); - chDbgCheck(sdp != NULL, "sdRequestDataI"); - - b = chOQGetI(&sdp->oqueue); - if (b < Q_OK) - chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); - return b; -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c deleted file mode 100644 index ff6e94b07..000000000 --- a/os/hal/src/serial_usb.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file serial_usb.c - * @brief Serial over USB Driver code. - * - * @addtogroup SERIAL_USB - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/* - * Current Line Coding. - */ -static cdc_linecoding_t linecoding = { - {0x00, 0x96, 0x00, 0x00}, /* 38400. */ - LC_STOP_1, LC_PARITY_NONE, 8 -}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/* - * Interface implementation. - */ - -static size_t write(void *ip, const uint8_t *bp, size_t n) { - - return chOQWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, - n, TIME_INFINITE); -} - -static size_t read(void *ip, uint8_t *bp, size_t n) { - - return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, - n, TIME_INFINITE); -} - -static msg_t put(void *ip, uint8_t b) { - - return chOQPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE); -} - -static msg_t get(void *ip) { - - return chIQGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE); -} - -static msg_t putt(void *ip, uint8_t b, systime_t timeout) { - - return chOQPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout); -} - -static msg_t gett(void *ip, systime_t timeout) { - - return chIQGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout); -} - -static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { - - return chOQWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, time); -} - -static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { - - return chIQReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, time); -} - -static const struct SerialUSBDriverVMT vmt = { - write, read, put, get, - putt, gett, writet, readt -}; - -/** - * @brief Notification of data removed from the input queue. - */ -static void inotify(GenericQueue *qp) { - size_t n, maxsize; - SerialUSBDriver *sdup = chQGetLink(qp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) - return; - - /* If there is in the queue enough space to hold at least one packet and - a transaction is not yet started then a new transaction is started for - the available space.*/ - maxsize = sdup->config->usbp->epc[sdup->config->bulk_out]->out_maxsize; - if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out) && - ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) { - chSysUnlock(); - - n = (n / maxsize) * maxsize; - usbPrepareQueuedReceive(sdup->config->usbp, - sdup->config->bulk_out, - &sdup->iqueue, n); - - chSysLock(); - usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); - } -} - -/** - * @brief Notification of data inserted into the output queue. - */ -static void onotify(GenericQueue *qp) { - size_t n; - SerialUSBDriver *sdup = chQGetLink(qp); - - /* If the USB driver is not in the appropriate state then transactions - must not be started.*/ - if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || - (sdup->state != SDU_READY)) - return; - - /* If there is not an ongoing transaction and the output queue contains - data then a new transaction is started.*/ - if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in) && - ((n = chOQGetFullI(&sdup->oqueue)) > 0)) { - chSysUnlock(); - - usbPrepareQueuedTransmit(sdup->config->usbp, - sdup->config->bulk_in, - &sdup->oqueue, n); - - chSysLock(); - usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in); - } -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Serial Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void sduInit(void) { -} - -/** - * @brief Initializes a generic full duplex driver object. - * @details The HW dependent part of the initialization has to be performed - * outside, usually in the hardware initialization code. - * - * @param[out] sdup pointer to a @p SerialUSBDriver structure - * - * @init - */ -void sduObjectInit(SerialUSBDriver *sdup) { - - sdup->vmt = &vmt; - chEvtInit(&sdup->event); - sdup->state = SDU_STOP; - chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup); - chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup); -} - -/** - * @brief Configures and starts the driver. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * @param[in] config the serial over USB driver configuration - * - * @api - */ -void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { - USBDriver *usbp = config->usbp; - - chDbgCheck(sdup != NULL, "sduStart"); - - chSysLock(); - chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), - "sduStart(), #1", - "invalid state"); - usbp->in_params[config->bulk_in - 1] = sdup; - usbp->out_params[config->bulk_out - 1] = sdup; - usbp->in_params[config->int_in - 1] = sdup; - sdup->config = config; - sdup->state = SDU_READY; - chSysUnlock(); -} - -/** - * @brief Stops the driver. - * @details Any thread waiting on the driver's queues will be awakened with - * the message @p Q_RESET. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @api - */ -void sduStop(SerialUSBDriver *sdup) { - USBDriver *usbp = sdup->config->usbp; - - chDbgCheck(sdup != NULL, "sdStop"); - - chSysLock(); - - chDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), - "sduStop(), #1", - "invalid state"); - - /* Driver in stopped state.*/ - usbp->in_params[sdup->config->bulk_in - 1] = NULL; - usbp->out_params[sdup->config->bulk_out - 1] = NULL; - usbp->in_params[sdup->config->int_in - 1] = NULL; - sdup->state = SDU_STOP; - - /* Queues reset in order to signal the driver stop to the application.*/ - chnAddFlagsI(sdup, CHN_DISCONNECTED); - chIQResetI(&sdup->iqueue); - chOQResetI(&sdup->oqueue); - chSchRescheduleS(); - - chSysUnlock(); -} - -/** - * @brief USB device configured handler. - * - * @param[in] sdup pointer to a @p SerialUSBDriver object - * - * @iclass - */ -void sduConfigureHookI(SerialUSBDriver *sdup) { - USBDriver *usbp = sdup->config->usbp; - - chIQResetI(&sdup->iqueue); - chOQResetI(&sdup->oqueue); - chnAddFlagsI(sdup, CHN_CONNECTED); - - /* Starts the first OUT transaction immediately.*/ - usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue, - usbp->epc[sdup->config->bulk_out]->out_maxsize); - usbStartReceiveI(usbp, sdup->config->bulk_out); -} - -/** - * @brief Default requests hook. - * @details Applications wanting to use the Serial over USB driver can use - * this function as requests hook in the USB configuration. - * The following requests are emulated: - * - CDC_GET_LINE_CODING. - * - CDC_SET_LINE_CODING. - * - CDC_SET_CONTROL_LINE_STATE. - * . - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The hook status. - * @retval TRUE Message handled internally. - * @retval FALSE Message not handled. - */ -bool_t sduRequestsHook(USBDriver *usbp) { - - if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { - switch (usbp->setup[1]) { - case CDC_GET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); - return TRUE; - case CDC_SET_LINE_CODING: - usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); - return TRUE; - case CDC_SET_CONTROL_LINE_STATE: - /* Nothing to do, there are no control lines.*/ - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - default: - return FALSE; - } - } - return FALSE; -} - -/** - * @brief Default data transmitted callback. - * @details The application must use this function as callback for the IN - * data endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - */ -void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { - size_t n; - SerialUSBDriver *sdup = usbp->in_params[ep - 1]; - - if (sdup == NULL) - return; - - chSysLockFromIsr(); - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - - if ((n = chOQGetFullI(&sdup->oqueue)) > 0) { - /* The endpoint cannot be busy, we are in the context of the callback, - so it is safe to transmit without a check.*/ - chSysUnlockFromIsr(); - - usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n); - - chSysLockFromIsr(); - usbStartTransmitI(usbp, ep); - } - else if ((usbp->epc[ep]->in_state->txsize > 0) && - !(usbp->epc[ep]->in_state->txsize & - (usbp->epc[ep]->in_maxsize - 1))) { - /* Transmit zero sized packet in case the last one has maximum allowed - size. Otherwise the recipient may expect more data coming soon and - not return buffered data to app. See section 5.8.3 Bulk Transfer - Packet Size Constraints of the USB Specification document.*/ - chSysUnlockFromIsr(); - - usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0); - - chSysLockFromIsr(); - usbStartTransmitI(usbp, ep); - } - - chSysUnlockFromIsr(); -} - -/** - * @brief Default data received callback. - * @details The application must use this function as callback for the OUT - * data endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - */ -void sduDataReceived(USBDriver *usbp, usbep_t ep) { - size_t n, maxsize; - SerialUSBDriver *sdup = usbp->out_params[ep - 1]; - - if (sdup == NULL) - return; - - chSysLockFromIsr(); - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - - /* Writes to the input queue can only happen when there is enough space - to hold at least one packet.*/ - maxsize = usbp->epc[ep]->out_maxsize; - if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) { - /* The endpoint cannot be busy, we are in the context of the callback, - so a packet is in the buffer for sure.*/ - chSysUnlockFromIsr(); - - n = (n / maxsize) * maxsize; - usbPrepareQueuedReceive(usbp, ep, &sdup->iqueue, n); - - chSysLockFromIsr(); - usbStartReceiveI(usbp, ep); - } - - chSysUnlockFromIsr(); -} - -/** - * @brief Default data received callback. - * @details The application must use this function as callback for the IN - * interrupt endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - */ -void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { - - (void)usbp; - (void)ep; -} - -#endif /* HAL_USE_SERIAL */ - -/** @} */ diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c deleted file mode 100644 index b2ddf48d2..000000000 --- a/os/hal/src/spi.c +++ /dev/null @@ -1,439 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file spi.c - * @brief SPI Driver code. - * - * @addtogroup SPI - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_SPI || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief SPI Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void spiInit(void) { - - spi_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p SPIDriver structure. - * - * @param[out] spip pointer to the @p SPIDriver object - * - * @init - */ -void spiObjectInit(SPIDriver *spip) { - - spip->state = SPI_STOP; - spip->config = NULL; -#if SPI_USE_WAIT - spip->thread = NULL; -#endif /* SPI_USE_WAIT */ -#if SPI_USE_MUTUAL_EXCLUSION -#if CH_CFG_USE_MUTEXES - chMtxInit(&spip->mutex); -#else - chSemInit(&spip->semaphore, 1); -#endif -#endif /* SPI_USE_MUTUAL_EXCLUSION */ -#if defined(SPI_DRIVER_EXT_INIT_HOOK) - SPI_DRIVER_EXT_INIT_HOOK(spip); -#endif -} - -/** - * @brief Configures and activates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] config pointer to the @p SPIConfig object - * - * @api - */ -void spiStart(SPIDriver *spip, const SPIConfig *config) { - - chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); - - chSysLock(); - chDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "spiStart(), #1", "invalid state"); - spip->config = config; - spi_lld_start(spip); - spip->state = SPI_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the SPI peripheral. - * @note Deactivating the peripheral also enforces a release of the slave - * select line. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiStop(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiStop"); - - chSysLock(); - chDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "spiStop(), #1", "invalid state"); - spi_lld_stop(spip); - spip->state = SPI_STOP; - chSysUnlock(); -} - -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiSelect(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiSelect"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiSelect(), #1", "not ready"); - spiSelectI(spip); - chSysUnlock(); -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiUnselect(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiUnselect"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiUnselect(), #1", "not ready"); - spiUnselectI(spip); - chSysUnlock(); -} - -/** - * @brief Ignores data on the SPI bus. - * @details This asynchronous function starts the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @api - */ -void spiStartIgnore(SPIDriver *spip, size_t n) { - - chDbgCheck((spip != NULL) && (n > 0), "spiStartIgnore"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiStartIgnore(), #1", "not ready"); - spiStartIgnoreI(spip, n); - chSysUnlock(); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This asynchronous function starts a simultaneous transmit/receive - * operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiStartExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), - "spiStartExchange"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiStartExchange(), #1", "not ready"); - spiStartExchangeI(spip, n, txbuf, rxbuf); - chSysUnlock(); -} - -/** - * @brief Sends data over the SPI bus. - * @details This asynchronous function starts a transmit operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), - "spiStartSend"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiStartSend(), #1", "not ready"); - spiStartSendI(spip, n, txbuf); - chSysUnlock(); -} - -/** - * @brief Receives data from the SPI bus. - * @details This asynchronous function starts a receive operation. - * @pre A slave must have been selected using @p spiSelect() or - * @p spiSelectI(). - * @post At the end of the operation the configured callback is invoked. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), - "spiStartReceive"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiStartReceive(), #1", "not ready"); - spiStartReceiveI(spip, n, rxbuf); - chSysUnlock(); -} - -#if SPI_USE_WAIT || defined(__DOXYGEN__) -/** - * @brief Ignores data on the SPI bus. - * @details This synchronous function performs the transmission of a series of - * idle words on the SPI bus and ignores the received data. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - * - * @api - */ -void spiIgnore(SPIDriver *spip, size_t n) { - - chDbgCheck((spip != NULL) && (n > 0), "spiIgnoreWait"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiIgnore(), #1", "not ready"); - chDbgAssert(spip->config->end_cb == NULL, "spiIgnore(), #2", "has callback"); - spiStartIgnoreI(spip, n); - _spi_wait_s(spip); - chSysUnlock(); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This synchronous function performs a simultaneous transmit/receive - * operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be exchanged - * @param[in] txbuf the pointer to the transmit buffer - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), - "spiExchange"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiExchange(), #1", "not ready"); - chDbgAssert(spip->config->end_cb == NULL, - "spiExchange(), #2", "has callback"); - spiStartExchangeI(spip, n, txbuf, rxbuf); - _spi_wait_s(spip); - chSysUnlock(); -} - -/** - * @brief Sends data over the SPI bus. - * @details This synchronous function performs a transmit operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), "spiSend"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiSend(), #1", "not ready"); - chDbgAssert(spip->config->end_cb == NULL, "spiSend(), #2", "has callback"); - spiStartSendI(spip, n, txbuf); - _spi_wait_s(spip); - chSysUnlock(); -} - -/** - * @brief Receives data from the SPI bus. - * @details This synchronous function performs a receive operation. - * @pre In order to use this function the option @p SPI_USE_WAIT must be - * enabled. - * @pre In order to use this function the driver must have been configured - * without callbacks (@p end_cb = @p NULL). - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to receive - * @param[out] rxbuf the pointer to the receive buffer - * - * @api - */ -void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), - "spiReceive"); - - chSysLock(); - chDbgAssert(spip->state == SPI_READY, "spiReceive(), #1", "not ready"); - chDbgAssert(spip->config->end_cb == NULL, - "spiReceive(), #2", "has callback"); - spiStartReceiveI(spip, n, rxbuf); - _spi_wait_s(spip); - chSysUnlock(); -} -#endif /* SPI_USE_WAIT */ - -#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the SPI bus. - * @details This function tries to gain ownership to the SPI bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiAcquireBus(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiAcquireBus"); - -#if CH_CFG_USE_MUTEXES - chMtxLock(&spip->mutex); -#elif CH_CFG_USE_SEMAPHORES - chSemWait(&spip->semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the SPI bus. - * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @api - */ -void spiReleaseBus(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiReleaseBus"); - -#if CH_CFG_USE_MUTEXES - (void)spip; - chMtxUnlock(); -#elif CH_CFG_USE_SEMAPHORES - chSemSignal(&spip->semaphore); -#endif -} -#endif /* SPI_USE_MUTUAL_EXCLUSION */ - -#endif /* HAL_USE_SPI */ - -/** @} */ diff --git a/os/hal/src/tm.c b/os/hal/src/tm.c deleted file mode 100644 index 5b002cd90..000000000 --- a/os/hal/src/tm.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file tm.c - * @brief Time Measurement driver code. - * - * @addtogroup TM - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_TM || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/** - * @brief Subsystem calibration value. - */ -static halrtcnt_t measurement_offset; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Starts a measurement. - * - * @param[in,out] tmp pointer to a @p TimeMeasurement structure - * - * @notapi - */ -static void tm_start(TimeMeasurement *tmp) { - - tmp->last = halGetCounterValue(); -} - -/** - * @brief Stops a measurement. - * - * @param[in,out] tmp pointer to a @p TimeMeasurement structure - * - * @notapi - */ -static void tm_stop(TimeMeasurement *tmp) { - - halrtcnt_t now = halGetCounterValue(); - tmp->last = now - tmp->last - measurement_offset; - if (tmp->last > tmp->worst) - tmp->worst = tmp->last; - else if (tmp->last < tmp->best) - tmp->best = tmp->last; -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Initializes the Time Measurement unit. - * - * @init - */ -void tmInit(void) { - TimeMeasurement tm; - - /* Time Measurement subsystem calibration, it does a null measurement - and calculates the call overhead which is subtracted to real - measurements.*/ - measurement_offset = 0; - tmObjectInit(&tm); - tmStartMeasurement(&tm); - tmStopMeasurement(&tm); - measurement_offset = tm.last; -} - -/** - * @brief Initializes a @p TimeMeasurement object. - * - * @param[out] tmp pointer to a @p TimeMeasurement structure - * - * @init - */ -void tmObjectInit(TimeMeasurement *tmp) { - - tmp->start = tm_start; - tmp->stop = tm_stop; - tmp->last = (halrtcnt_t)0; - tmp->worst = (halrtcnt_t)0; - tmp->best = (halrtcnt_t)-1; -} - -#endif /* HAL_USE_TM */ - -/** @} */ diff --git a/os/hal/src/uart.c b/os/hal/src/uart.c deleted file mode 100644 index 71869538d..000000000 --- a/os/hal/src/uart.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file uart.c - * @brief UART Driver code. - * - * @addtogroup UART - * @{ - */ - -#include "ch.h" -#include "hal.h" - -#if HAL_USE_UART || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief UART Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void uartInit(void) { - - uart_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p UARTDriver structure. - * - * @param[out] uartp pointer to the @p UARTDriver object - * - * @init - */ -void uartObjectInit(UARTDriver *uartp) { - - uartp->state = UART_STOP; - uartp->txstate = UART_TX_IDLE; - uartp->rxstate = UART_RX_IDLE; - uartp->config = NULL; - /* Optional, user-defined initializer.*/ -#if defined(UART_DRIVER_EXT_INIT_HOOK) - UART_DRIVER_EXT_INIT_HOOK(uartp); -#endif -} - -/** - * @brief Configures and activates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] config pointer to the @p UARTConfig object - * - * @api - */ -void uartStart(UARTDriver *uartp, const UARTConfig *config) { - - chDbgCheck((uartp != NULL) && (config != NULL), "uartStart"); - - chSysLock(); - chDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), - "uartStart(), #1", "invalid state"); - - uartp->config = config; - uart_lld_start(uartp); - uartp->state = UART_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the UART peripheral. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @api - */ -void uartStop(UARTDriver *uartp) { - - chDbgCheck(uartp != NULL, "uartStop"); - - chSysLock(); - chDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), - "uartStop(), #1", "invalid state"); - - uart_lld_stop(uartp); - uartp->state = UART_STOP; - uartp->txstate = UART_TX_IDLE; - uartp->rxstate = UART_RX_IDLE; - chSysUnlock(); -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @api - */ -void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) { - - chDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL), - "uartStartSend"); - - chSysLock(); - chDbgAssert(uartp->state == UART_READY, - "uartStartSend(), #1", "is active"); - chDbgAssert(uartp->txstate != UART_TX_ACTIVE, - "uartStartSend(), #2", "tx active"); - - uart_lld_start_send(uartp, n, txbuf); - uartp->txstate = UART_TX_ACTIVE; - chSysUnlock(); -} - -/** - * @brief Starts a transmission on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] txbuf the pointer to the transmit buffer - * - * @iclass - */ -void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { - - chDbgCheckClassI(); - chDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL), - "uartStartSendI"); - chDbgAssert(uartp->state == UART_READY, - "uartStartSendI(), #1", "is active"); - chDbgAssert(uartp->txstate != UART_TX_ACTIVE, - "uartStartSendI(), #2", "tx active"); - - uart_lld_start_send(uartp, n, txbuf); - uartp->txstate = UART_TX_ACTIVE; -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * @retval 0 There was no transmit operation in progress. - * - * @api - */ -size_t uartStopSend(UARTDriver *uartp) { - size_t n; - - chDbgCheck(uartp != NULL, "uartStopSend"); - - chSysLock(); - chDbgAssert(uartp->state == UART_READY, "uartStopSend(), #1", "not active"); - - if (uartp->txstate == UART_TX_ACTIVE) { - n = uart_lld_stop_send(uartp); - uartp->txstate = UART_TX_IDLE; - } - else - n = 0; - chSysUnlock(); - return n; -} - -/** - * @brief Stops any ongoing transmission. - * @note Stopping a transmission also suppresses the transmission callbacks. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not transmitted by the - * stopped transmit operation. - * @retval 0 There was no transmit operation in progress. - * - * @iclass - */ -size_t uartStopSendI(UARTDriver *uartp) { - - chDbgCheckClassI(); - chDbgCheck(uartp != NULL, "uartStopSendI"); - chDbgAssert(uartp->state == UART_READY, "uartStopSendI(), #1", "not active"); - - if (uartp->txstate == UART_TX_ACTIVE) { - size_t n = uart_lld_stop_send(uartp); - uartp->txstate = UART_TX_IDLE; - return n; - } - return 0; -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[in] rxbuf the pointer to the receive buffer - * - * @api - */ -void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) { - - chDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL), - "uartStartReceive"); - - chSysLock(); - chDbgAssert(uartp->state == UART_READY, - "uartStartReceive(), #1", "is active"); - chDbgAssert(uartp->rxstate != UART_RX_ACTIVE, - "uartStartReceive(), #2", "rx active"); - - uart_lld_start_receive(uartp, n, rxbuf); - uartp->rxstate = UART_RX_ACTIVE; - chSysUnlock(); -} - -/** - * @brief Starts a receive operation on the UART peripheral. - * @note The buffers are organized as uint8_t arrays for data sizes below - * or equal to 8 bits else it is organized as uint16_t arrays. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * @param[in] n number of data frames to send - * @param[out] rxbuf the pointer to the receive buffer - * - * @iclass - */ -void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { - - chDbgCheckClassI(); - chDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL), - "uartStartReceiveI"); - chDbgAssert(uartp->state == UART_READY, - "uartStartReceiveI(), #1", "is active"); - chDbgAssert(uartp->rxstate != UART_RX_ACTIVE, - "uartStartReceiveI(), #2", "rx active"); - - uart_lld_start_receive(uartp, n, rxbuf); - uartp->rxstate = UART_RX_ACTIVE; -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * @retval 0 There was no receive operation in progress. - * - * @api - */ -size_t uartStopReceive(UARTDriver *uartp) { - size_t n; - - chDbgCheck(uartp != NULL, "uartStopReceive"); - - chSysLock(); - chDbgAssert(uartp->state == UART_READY, - "uartStopReceive(), #1", "not active"); - - if (uartp->rxstate == UART_RX_ACTIVE) { - n = uart_lld_stop_receive(uartp); - uartp->rxstate = UART_RX_IDLE; - } - else - n = 0; - chSysUnlock(); - return n; -} - -/** - * @brief Stops any ongoing receive operation. - * @note Stopping a receive operation also suppresses the receive callbacks. - * @note This function has to be invoked from a lock zone. - * - * @param[in] uartp pointer to the @p UARTDriver object - * - * @return The number of data frames not received by the - * stopped receive operation. - * @retval 0 There was no receive operation in progress. - * - * @iclass - */ -size_t uartStopReceiveI(UARTDriver *uartp) { - - chDbgCheckClassI(); - chDbgCheck(uartp != NULL, "uartStopReceiveI"); - chDbgAssert(uartp->state == UART_READY, - "uartStopReceiveI(), #1", "not active"); - - if (uartp->rxstate == UART_RX_ACTIVE) { - size_t n = uart_lld_stop_receive(uartp); - uartp->rxstate = UART_RX_IDLE; - return n; - } - return 0; -} - -#endif /* HAL_USE_UART */ - -/** @} */ diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c deleted file mode 100644 index 1da532abf..000000000 --- a/os/hal/src/usb.c +++ /dev/null @@ -1,780 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file usb.c - * @brief USB Driver code. - * - * @addtogroup USB - * @{ - */ - -#include - -#include "ch.h" -#include "hal.h" -#include "usb.h" - -#if HAL_USE_USB || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -static const uint8_t zero_status[] = {0x00, 0x00}; -static const uint8_t active_status[] ={0x00, 0x00}; -static const uint8_t halted_status[] = {0x01, 0x00}; - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief SET ADDRESS transaction callback. - * - * @param[in] usbp pointer to the @p USBDriver object - */ -static void set_address(USBDriver *usbp) { - - usbp->address = usbp->setup[2]; - usb_lld_set_address(usbp); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS); - usbp->state = USB_SELECTED; -} - -/** - * @brief Standard requests handler. - * @details This is the standard requests default handler, most standard - * requests are handled here, the user can override the standard - * handling using the @p requests_hook_cb hook in the - * @p USBConfig structure. - * - * @param[in] usbp pointer to the @p USBDriver object - * @return The request handling exit code. - * @retval FALSE Request not recognized by the handler or error. - * @retval TRUE Request handled. - */ -static bool_t default_handler(USBDriver *usbp) { - const USBDescriptor *dp; - - /* Decoding the request.*/ - switch (((usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | - USB_RTYPE_TYPE_MASK)) | - (usbp->setup[1] << 8))) { - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_STATUS << 8): - /* Just returns the current status word.*/ - usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_CLEAR_FEATURE << 8): - /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature - number is handled as an error.*/ - if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { - usbp->status &= ~2; - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - } - return FALSE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_FEATURE << 8): - /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature - number is handled as an error.*/ - if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { - usbp->status |= 2; - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - } - return FALSE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_ADDRESS << 8): - /* The SET_ADDRESS handling can be performed here or postponed after - the status packed depending on the USB_SET_ADDRESS_MODE low - driver setting.*/ -#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS - if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) && - (usbp->setup[1] == USB_REQ_SET_ADDRESS)) - set_address(usbp); - usbSetupTransfer(usbp, NULL, 0, NULL); -#else - usbSetupTransfer(usbp, NULL, 0, set_address); -#endif - return TRUE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_DESCRIPTOR << 8): - /* Handling descriptor requests from the host.*/ - dp = usbp->config->get_descriptor_cb( - usbp, usbp->setup[3], usbp->setup[2], - usbFetchWord(&usbp->setup[4])); - if (dp == NULL) - return FALSE; - usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_CONFIGURATION << 8): - /* Returning the last selected configuration.*/ - usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_CONFIGURATION << 8): - /* Handling configuration selection from the host.*/ - usbp->configuration = usbp->setup[2]; - if (usbp->configuration == 0) - usbp->state = USB_SELECTED; - else - usbp->state = USB_ACTIVE; - _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_STATUS << 8): - case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SYNCH_FRAME << 8): - /* Just sending two zero bytes, the application can change the behavior - using a hook..*/ - usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_GET_STATUS << 8): - /* Sending the EP status.*/ - if (usbp->setup[4] & 0x80) { - switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0F)) { - case EP_STATUS_STALLED: - usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); - return TRUE; - case EP_STATUS_ACTIVE: - usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); - return TRUE; - default: - return FALSE; - } - } - else { - switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0F)) { - case EP_STATUS_STALLED: - usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); - return TRUE; - case EP_STATUS_ACTIVE: - usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); - return TRUE; - default: - return FALSE; - } - } - case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_CLEAR_FEATURE << 8): - /* Only ENDPOINT_HALT is handled as feature.*/ - if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) - return FALSE; - /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/ - if ((usbp->setup[4] & 0x0F) > 0) { - if (usbp->setup[4] & 0x80) - usb_lld_clear_in(usbp, usbp->setup[4] & 0x0F); - else - usb_lld_clear_out(usbp, usbp->setup[4] & 0x0F); - } - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SET_FEATURE << 8): - /* Only ENDPOINT_HALT is handled as feature.*/ - if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) - return FALSE; - /* Stalling the EP, not valid for EP0, it is ignored in that case.*/ - if ((usbp->setup[4] & 0x0F) > 0) { - if (usbp->setup[4] & 0x80) - usb_lld_stall_in(usbp, usbp->setup[4] & 0x0F); - else - usb_lld_stall_out(usbp, usbp->setup[4] & 0x0F); - } - usbSetupTransfer(usbp, NULL, 0, NULL); - return TRUE; - case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_DESCRIPTOR << 8): - case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_CLEAR_FEATURE << 8): - case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_FEATURE << 8): - case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_INTERFACE << 8): - case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_INTERFACE << 8): - /* All the above requests are not handled here, if you need them then - use the hook mechanism and provide handling.*/ - default: - return FALSE; - } -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief USB Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void usbInit(void) { - - usb_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p USBDriver structure. - * - * @param[out] usbp pointer to the @p USBDriver object - * - * @init - */ -void usbObjectInit(USBDriver *usbp) { - unsigned i; - - usbp->state = USB_STOP; - usbp->config = NULL; - for (i = 0; i < USB_MAX_ENDPOINTS; i++) { - usbp->in_params[i] = NULL; - usbp->out_params[i] = NULL; - } - usbp->transmitting = 0; - usbp->receiving = 0; -} - -/** - * @brief Configures and activates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] config pointer to the @p USBConfig object - * - * @api - */ -void usbStart(USBDriver *usbp, const USBConfig *config) { - unsigned i; - - chDbgCheck((usbp != NULL) && (config != NULL), "usbStart"); - - chSysLock(); - chDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY), - "usbStart(), #1", "invalid state"); - usbp->config = config; - for (i = 0; i <= USB_MAX_ENDPOINTS; i++) - usbp->epc[i] = NULL; - usb_lld_start(usbp); - usbp->state = USB_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the USB peripheral. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @api - */ -void usbStop(USBDriver *usbp) { - - chDbgCheck(usbp != NULL, "usbStop"); - - chSysLock(); - chDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || - (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE), - "usbStop(), #1", "invalid state"); - usb_lld_stop(usbp); - usbp->state = USB_STOP; - chSysUnlock(); -} - -/** - * @brief Enables an endpoint. - * @details This function enables an endpoint, both IN and/or OUT directions - * depending on the configuration structure. - * @note This function must be invoked in response of a SET_CONFIGURATION - * or SET_INTERFACE message. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] epcp the endpoint configuration - * - * @iclass - */ -void usbInitEndpointI(USBDriver *usbp, usbep_t ep, - const USBEndpointConfig *epcp) { - - chDbgCheckClassI(); - chDbgCheck((usbp != NULL) && (epcp != NULL), "usbInitEndpointI"); - chDbgAssert(usbp->state == USB_ACTIVE, - "usbEnableEndpointI(), #1", "invalid state"); - chDbgAssert(usbp->epc[ep] == NULL, - "usbEnableEndpointI(), #2", "already initialized"); - - /* Logically enabling the endpoint in the USBDriver structure.*/ - if (epcp->in_state != NULL) - memset(epcp->in_state, 0, sizeof(USBInEndpointState)); - if (epcp->out_state != NULL) - memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); - - usbp->epc[ep] = epcp; - - /* Low level endpoint activation.*/ - usb_lld_init_endpoint(usbp, ep); -} - -/** - * @brief Disables all the active endpoints. - * @details This function disables all the active endpoints except the - * endpoint zero. - * @note This function must be invoked in response of a SET_CONFIGURATION - * message with configuration number zero. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @iclass - */ -void usbDisableEndpointsI(USBDriver *usbp) { - unsigned i; - - chDbgCheckClassI(); - chDbgCheck(usbp != NULL, "usbDisableEndpointsI"); - chDbgAssert(usbp->state == USB_SELECTED, - "usbDisableEndpointsI(), #1", "invalid state"); - - usbp->transmitting &= ~1; - usbp->receiving &= ~1; - for (i = 1; i <= USB_MAX_ENDPOINTS; i++) - usbp->epc[i] = NULL; - - /* Low level endpoints deactivation.*/ - usb_lld_disable_endpoints(usbp); -} - -/** - * @brief Prepares for a receive transaction on an OUT endpoint. - * @post The endpoint is ready for @p usbStartReceiveI(). - * @note This function can be called both in ISR and thread context. - * - * @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 transaction size - * - * @special - */ -void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - osp->rxqueued = FALSE; - osp->mode.linear.rxbuf = buf; - osp->rxsize = n; - osp->rxcnt = 0; - - usb_lld_prepare_receive(usbp, ep); -} - -/** - * @brief Prepares for a transmit transaction on an IN endpoint. - * @post The endpoint is ready for @p usbStartTransmitI(). - * @note This function can be called both in ISR and thread context. - * @note The queue must contain at least the amount of data specified - * as transaction size. - * - * @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 transaction size - * - * @special - */ -void usbPrepareTransmit(USBDriver *usbp, usbep_t ep, - const uint8_t *buf, size_t n) { - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - isp->txqueued = FALSE; - isp->mode.linear.txbuf = buf; - isp->txsize = n; - isp->txcnt = 0; - - usb_lld_prepare_transmit(usbp, ep); -} - -/** - * @brief Prepares for a receive transaction on an OUT endpoint. - * @post The endpoint is ready for @p usbStartReceiveI(). - * @note This function can be called both in ISR and thread context. - * @note The queue must have enough free space to accommodate the - * specified transaction size rounded to the next packet size - * boundary. For example if the transaction size is 1 and the - * packet size is 64 then the queue must have space for at least - * 64 bytes. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] iqp input queue to be filled with incoming data - * @param[in] n transaction size - * - * @special - */ -void usbPrepareQueuedReceive(USBDriver *usbp, usbep_t ep, - InputQueue *iqp, size_t n) { - USBOutEndpointState *osp = usbp->epc[ep]->out_state; - - osp->rxqueued = TRUE; - osp->mode.queue.rxqueue = iqp; - osp->rxsize = n; - osp->rxcnt = 0; - - usb_lld_prepare_receive(usbp, ep); -} - -/** - * @brief Prepares for a transmit transaction on an IN endpoint. - * @post The endpoint is ready for @p usbStartTransmitI(). - * @note This function can be called both in ISR and thread context. - * @note The transmit transaction size is equal to the data contained - * in the queue. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * @param[in] oqp output queue to be fetched for outgoing data - * @param[in] n transaction size - * - * @special - */ -void usbPrepareQueuedTransmit(USBDriver *usbp, usbep_t ep, - OutputQueue *oqp, size_t n) { - USBInEndpointState *isp = usbp->epc[ep]->in_state; - - isp->txqueued = TRUE; - isp->mode.queue.txqueue = oqp; - isp->txsize = n; - isp->txcnt = 0; - - usb_lld_prepare_transmit(usbp, ep); -} - -/** - * @brief Starts a receive transaction on an OUT endpoint. - * @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 - * - * @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) { - - chDbgCheckClassI(); - chDbgCheck(usbp != NULL, "usbStartReceiveI"); - - if (usbGetReceiveStatusI(usbp, ep)) - return TRUE; - - usbp->receiving |= (1 << ep); - usb_lld_start_out(usbp, ep); - return FALSE; -} - -/** - * @brief Starts a transmit transaction on an IN endpoint. - * @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 - * - * @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) { - - chDbgCheckClassI(); - chDbgCheck(usbp != NULL, "usbStartTransmitI"); - - if (usbGetTransmitStatusI(usbp, ep)) - return TRUE; - - usbp->transmitting |= (1 << ep); - usb_lld_start_in(usbp, ep); - return FALSE; -} - -/** - * @brief Stalls an OUT endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @return The operation status. - * @retval FALSE Endpoint stalled. - * @retval TRUE Endpoint busy, not stalled. - * - * @iclass - */ -bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) { - - chDbgCheckClassI(); - chDbgCheck(usbp != NULL, "usbStallReceiveI"); - - if (usbGetReceiveStatusI(usbp, ep)) - return TRUE; - - usb_lld_stall_out(usbp, ep); - return FALSE; -} - -/** - * @brief Stalls an IN endpoint. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number - * - * @return The operation status. - * @retval FALSE Endpoint stalled. - * @retval TRUE Endpoint busy, not stalled. - * - * @iclass - */ -bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep) { - - chDbgCheckClassI(); - chDbgCheck(usbp != NULL, "usbStallTransmitI"); - - if (usbGetTransmitStatusI(usbp, ep)) - return TRUE; - - usb_lld_stall_in(usbp, ep); - return FALSE; -} - -/** - * @brief USB reset routine. - * @details This function must be invoked when an USB bus reset condition is - * detected. - * - * @param[in] usbp pointer to the @p USBDriver object - * - * @notapi - */ -void _usb_reset(USBDriver *usbp) { - unsigned i; - - usbp->state = USB_READY; - usbp->status = 0; - usbp->address = 0; - usbp->configuration = 0; - usbp->transmitting = 0; - usbp->receiving = 0; - - /* Invalidates all endpoints into the USBDriver structure.*/ - for (i = 0; i <= USB_MAX_ENDPOINTS; i++) - usbp->epc[i] = NULL; - - /* EP0 state machine initialization.*/ - usbp->ep0state = USB_EP0_WAITING_SETUP; - - /* Low level reset.*/ - usb_lld_reset(usbp); -} - -/** - * @brief Default EP0 SETUP callback. - * @details This function is used by the low level driver as default handler - * for EP0 SETUP events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { - size_t max; - - usbp->ep0state = USB_EP0_WAITING_SETUP; - usbReadSetup(usbp, ep, usbp->setup); - - /* First verify if the application has an handler installed for this - request.*/ - if (!(usbp->config->requests_hook_cb) || - !(usbp->config->requests_hook_cb(usbp))) { - /* Invoking the default handler, if this fails then stalls the - endpoint zero as error.*/ - if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) || - !default_handler(usbp)) { - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; - return; - } - } - - /* Transfer preparation. The request handler must have populated - correctly the fields ep0next, ep0n and ep0endcb using the macro - usbSetupTransfer().*/ - max = usbFetchWord(&usbp->setup[6]); - /* The transfer size cannot exceed the specified amount.*/ - if (usbp->ep0n > max) - usbp->ep0n = max; - if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { - /* IN phase.*/ - if (usbp->ep0n > 0) { - /* Starts the transmit phase.*/ - usbp->ep0state = USB_EP0_TX; - usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n); - chSysLockFromIsr(); - usbStartTransmitI(usbp, 0); - chSysUnlockFromIsr(); - } - else { - /* No transmission phase, directly receiving the zero sized status - packet.*/ - usbp->ep0state = USB_EP0_WAITING_STS; - usbPrepareReceive(usbp, 0, NULL, 0); - chSysLockFromIsr(); - usbStartReceiveI(usbp, 0); - chSysUnlockFromIsr(); - } - } - else { - /* OUT phase.*/ - if (usbp->ep0n > 0) { - /* Starts the receive phase.*/ - usbp->ep0state = USB_EP0_RX; - usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n); - chSysLockFromIsr(); - usbStartReceiveI(usbp, 0); - chSysUnlockFromIsr(); - } - else { - /* No receive phase, directly sending the zero sized status - packet.*/ - usbp->ep0state = USB_EP0_SENDING_STS; - usbPrepareTransmit(usbp, 0, NULL, 0); - chSysLockFromIsr(); - usbStartTransmitI(usbp, 0); - chSysUnlockFromIsr(); - } - } -} - -/** - * @brief Default EP0 IN callback. - * @details This function is used by the low level driver as default handler - * for EP0 IN events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0in(USBDriver *usbp, usbep_t ep) { - size_t max; - - (void)ep; - switch (usbp->ep0state) { - case USB_EP0_TX: - max = usbFetchWord(&usbp->setup[6]); - /* If the transmitted size is less than the requested size and it is a - multiple of the maximum packet size then a zero size packet must be - transmitted.*/ - if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) { - usbPrepareTransmit(usbp, 0, NULL, 0); - chSysLockFromIsr(); - usbStartTransmitI(usbp, 0); - chSysUnlockFromIsr(); - usbp->ep0state = USB_EP0_WAITING_TX0; - return; - } - /* Falls into, it is intentional.*/ - case USB_EP0_WAITING_TX0: - /* Transmit phase over, receiving the zero sized status packet.*/ - usbp->ep0state = USB_EP0_WAITING_STS; - usbPrepareReceive(usbp, 0, NULL, 0); - chSysLockFromIsr(); - usbStartReceiveI(usbp, 0); - chSysUnlockFromIsr(); - return; - case USB_EP0_SENDING_STS: - /* Status packet sent, invoking the callback if defined.*/ - if (usbp->ep0endcb != NULL) - usbp->ep0endcb(usbp); - usbp->ep0state = USB_EP0_WAITING_SETUP; - return; - default: - ; - } - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; -} - -/** - * @brief Default EP0 OUT callback. - * @details This function is used by the low level driver as default handler - * for EP0 OUT events. - * - * @param[in] usbp pointer to the @p USBDriver object - * @param[in] ep endpoint number, always zero - * - * @notapi - */ -void _usb_ep0out(USBDriver *usbp, usbep_t ep) { - - (void)ep; - switch (usbp->ep0state) { - case USB_EP0_RX: - /* Receive phase over, sending the zero sized status packet.*/ - usbp->ep0state = USB_EP0_SENDING_STS; - usbPrepareTransmit(usbp, 0, NULL, 0); - chSysLockFromIsr(); - usbStartTransmitI(usbp, 0); - chSysUnlockFromIsr(); - return; - case USB_EP0_WAITING_STS: - /* Status packet received, it must be zero sized, invoking the callback - if defined.*/ - if (usbGetReceiveTransactionSizeI(usbp, 0) != 0) - break; - if (usbp->ep0endcb != NULL) - usbp->ep0endcb(usbp); - usbp->ep0state = USB_EP0_WAITING_SETUP; - return; - default: - ; - } - /* Error response, the state machine goes into an error state, the low - level layer will have to reset it to USB_EP0_WAITING_SETUP after - receiving a SETUP packet.*/ - usb_lld_stall_in(usbp, 0); - usb_lld_stall_out(usbp, 0); - _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); - usbp->ep0state = USB_EP0_ERROR; -} - -#endif /* HAL_USE_USB */ - -/** @} */ -- cgit v1.2.3 From 0e34cd051ed686263001af3a721f6858db94d072 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Aug 2013 08:25:09 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6109 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/adc.c | 326 ++++++++++++++++++++++++++++++++++++ os/hal/src/can.c | 284 ++++++++++++++++++++++++++++++++ os/hal/src/hal.c | 132 +++++++++++++++ os/hal/src/hal_queues.c | 402 +++++++++++++++++++++++++++++++++++++++++++++ os/hal/src/icu.c | 158 ++++++++++++++++++ os/hal/src/pal.c | 123 ++++++++++++++ os/hal/src/pwm.c | 204 +++++++++++++++++++++++ os/hal/src/serial.c | 243 +++++++++++++++++++++++++++ os/hal/src/spi.c | 428 ++++++++++++++++++++++++++++++++++++++++++++++++ os/hal/src/st.c | 71 ++++++++ 10 files changed, 2371 insertions(+) create mode 100644 os/hal/src/adc.c create mode 100644 os/hal/src/can.c create mode 100644 os/hal/src/hal.c create mode 100644 os/hal/src/hal_queues.c create mode 100644 os/hal/src/icu.c create mode 100644 os/hal/src/pal.c create mode 100644 os/hal/src/pwm.c create mode 100644 os/hal/src/serial.c create mode 100644 os/hal/src/spi.c create mode 100644 os/hal/src/st.c (limited to 'os/hal/src') diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c new file mode 100644 index 000000000..ccc11574a --- /dev/null +++ b/os/hal/src/adc.c @@ -0,0 +1,326 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file adc.c + * @brief ADC Driver code. + * + * @addtogroup ADC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ADC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ADC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void adcInit(void) { + + adc_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p ADCDriver structure. + * + * @param[out] adcp pointer to the @p ADCDriver object + * + * @init + */ +void adcObjectInit(ADCDriver *adcp) { + + adcp->state = ADC_STOP; + adcp->config = NULL; + adcp->samples = NULL; + adcp->depth = 0; + adcp->grpp = NULL; +#if ADC_USE_WAIT + adcp->thread = NULL; +#endif /* ADC_USE_WAIT */ +#if ADC_USE_MUTUAL_EXCLUSION + osalMutexObjectInit(&adcp->mutex); +#endif /* ADC_USE_MUTUAL_EXCLUSION */ +#if defined(ADC_DRIVER_EXT_INIT_HOOK) + ADC_DRIVER_EXT_INIT_HOOK(adcp); +#endif +} + +/** + * @brief Configures and activates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] config pointer to the @p ADCConfig object. Depending on + * the implementation the value can be @p NULL. + * + * @api + */ +void adcStart(ADCDriver *adcp, const ADCConfig *config) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), + "adcStart(), #1", "invalid state"); + adcp->config = config; + adc_lld_start(adcp); + adcp->state = ADC_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcStop(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), + "adcStop(), #1", "invalid state"); + adc_lld_stop(adcp); + adcp->state = ADC_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts an ADC conversion. + * @details Starts an asynchronous conversion operation. + * @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 + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @api + */ +void adcStartConversion(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + + osalSysLock(); + adcStartConversionI(adcp, grpp, samples, depth); + osalSysUnlock(); +} + +/** + * @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 + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @iclass + */ +void adcStartConversionI(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + + osalDbgCheckClassI(); + osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && + ((depth == 1) || ((depth & 1) == 0))); + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_COMPLETE) || + (adcp->state == ADC_ERROR), + "adcStartConversionI(), #1", "not ready"); + + adcp->samples = samples; + adcp->depth = depth; + adcp->grpp = grpp; + adcp->state = ADC_ACTIVE; + adc_lld_start_conversion(adcp); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p ADC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcStopConversion(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalSysLock(); + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_ACTIVE), + "adcStopConversion(), #1", "invalid state"); + if (adcp->state != ADC_READY) { + adc_lld_stop_conversion(adcp); + adcp->grpp = NULL; + adcp->state = ADC_READY; + _adc_reset_s(adcp); + } + osalSysUnlock(); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p ADC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @iclass + */ +void adcStopConversionI(ADCDriver *adcp) { + + osalDbgCheckClassI(); + osalDbgCheck(adcp != NULL); + osalDbgAssert((adcp->state == ADC_READY) || + (adcp->state == ADC_ACTIVE) || + (adcp->state == ADC_COMPLETE), + "adcStopConversionI(), #1", "invalid state"); + + if (adcp->state != ADC_READY) { + adc_lld_stop_conversion(adcp); + adcp->grpp = NULL; + adcp->state = ADC_READY; + _adc_reset_i(adcp); + } +} + +#if ADC_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Performs an ADC conversion. + * @details Performs a synchronous conversion operation. + * @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 + * with no gaps. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @param[in] grpp pointer to a @p ADCConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * @return The operation result. + * @retval RDY_OK Conversion finished. + * @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 + */ +msg_t adcConvert(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth) { + msg_t msg; + + osalSysLock(); + osalDbgAssert(adcp->thread == NULL, "adcConvert(), #1", "already waiting"); + adcStartConversionI(adcp, grpp, samples, depth); + msg = osalThreadSuspendS(&adcp->thread); + osalSysUnlock(); + return msg; +} +#endif /* ADC_USE_WAIT */ + +#if ADC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the ADC peripheral. + * @details This function tries to gain ownership to the ADC bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option + * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcAcquireBus(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalMutexLock(&adcp->mutex); +} + +/** + * @brief Releases exclusive access to the ADC peripheral. + * @pre In order to use this function the option + * @p ADC_USE_MUTUAL_EXCLUSION must be enabled. + * + * @param[in] adcp pointer to the @p ADCDriver object + * + * @api + */ +void adcReleaseBus(ADCDriver *adcp) { + + osalDbgCheck(adcp != NULL); + + osalMutexUnlock(&adcp->mutex); +} +#endif /* ADC_USE_MUTUAL_EXCLUSION */ + +#endif /* HAL_USE_ADC */ + +/** @} */ diff --git a/os/hal/src/can.c b/os/hal/src/can.c new file mode 100644 index 000000000..9a352ddd1 --- /dev/null +++ b/os/hal/src/can.c @@ -0,0 +1,284 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file can.c + * @brief CAN Driver code. + * + * @addtogroup CAN + * @{ + */ + +#include "hal.h" + +#if HAL_USE_CAN || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief CAN Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void canInit(void) { + + can_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p CANDriver structure. + * + * @param[out] canp pointer to the @p CANDriver object + * + * @init + */ +void canObjectInit(CANDriver *canp) { + + canp->state = CAN_STOP; + canp->config = NULL; + osalQueueObjectInit(&canp->txqueue); + osalQueueObjectInit(&canp->rxqueue); + osalEventObjectInit(&canp->rxfull_event); + osalEventObjectInit(&canp->txempty_event); + osalEventObjectInit(&canp->error_event); +#if CAN_USE_SLEEP_MODE + osalEventObjectInit(&canp->sleep_event); + osalEventObjectInit(&canp->wakeup_event); +#endif /* CAN_USE_SLEEP_MODE */ +} + +/** + * @brief Configures and activates the CAN peripheral. + * @note Activating the CAN bus can be a slow operation this this function + * is not atomic, it waits internally for the initialization to + * complete. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] config pointer to the @p CANConfig object. Depending on + * the implementation the value can be @p NULL. + * + * @api + */ +void canStart(CANDriver *canp, const CANConfig *config) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_STOP) || + (canp->state == CAN_STARTING) || + (canp->state == CAN_READY), + "canStart(), #1", "invalid state"); + while (canp->state == CAN_STARTING) + osalThreadSleepS(1); + if (canp->state == CAN_STOP) { + canp->config = config; + can_lld_start(canp); + canp->state = CAN_READY; + } + osalSysUnlock(); +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @api + */ +void canStop(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), + "canStop(), #1", "invalid state"); + can_lld_stop(canp); + canp->state = CAN_STOP; + osalQueueWakeupAllI(&canp->rxqueue, MSG_RESET); + osalQueueWakeupAllI(&canp->txqueue, MSG_RESET); + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief Can frame transmission. + * @details The specified frame is queued for transmission, if the hardware + * queue is full then the invoking thread is queued. + * @note Trying to transmit while in sleep mode simply enqueues the thread. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[in] ctfp pointer to the CAN frame to be transmitted + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation result. + * @retval MSG_OK the frame has been queued for transmission. + * @retval MSG_TIMEOUT The operation has timed out. + * @retval MSG_RESET The driver has been stopped while waiting. + * + * @api + */ +msg_t canTransmit(CANDriver *canp, + canmbx_t mailbox, + const CANTxFrame *ctfp, + systime_t timeout) { + + osalDbgCheck((canp != NULL) && (ctfp != NULL) && + (mailbox <= CAN_TX_MAILBOXES)); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "canTransmit(), #1", "invalid state"); + while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { + msg_t msg = osalQueueGoSleepTimeoutS(&canp->txqueue, timeout); + if (msg != MSG_OK) { + osalSysUnlock(); + return msg; + } + } + can_lld_transmit(canp, mailbox, ctfp); + osalSysUnlock(); + return MSG_OK; +} + +/** + * @brief Can frame receive. + * @details The function waits until a frame is received. + * @note Trying to receive while in sleep mode simply enqueues the thread. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox + * @param[out] crfp pointer to the buffer where the CAN frame is copied + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout (useful in an + * event driven scenario where a thread never blocks + * for I/O). + * - @a TIME_INFINITE no timeout. + * . + * @return The operation result. + * @retval MSG_OK a frame has been received and placed in the buffer. + * @retval MSG_TIMEOUT The operation has timed out. + * @retval MSG_RESET The driver has been stopped while waiting. + * + * @api + */ +msg_t canReceive(CANDriver *canp, + canmbx_t mailbox, + CANRxFrame *crfp, + systime_t timeout) { + + osalDbgCheck((canp != NULL) && (crfp != NULL) && + (mailbox < CAN_RX_MAILBOXES)); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "canReceive(), #1", "invalid state"); + while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { + msg_t msg = osalQueueGoSleepTimeoutS(&canp->rxqueue, timeout); + if (msg != MSG_OK) { + osalSysUnlock(); + return msg; + } + } + can_lld_receive(canp, mailbox, crfp); + osalSysUnlock(); + return MSG_OK; +} + +#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * @details This function puts the CAN driver in sleep mode and broadcasts + * the @p sleep_event event source. + * @pre In order to use this function the option @p CAN_USE_SLEEP_MODE must + * be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported + * by the low level driver. + * + * @param[in] canp pointer to the @p CANDriver object + * + * @api + */ +void canSleep(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "canSleep(), #1", "invalid state"); + if (canp->state == CAN_READY) { + can_lld_sleep(canp); + canp->state = CAN_SLEEP; + osalEventBroadcastFlagsI(&canp->sleep_event, 0); + osalOsRescheduleS(); + } + osalSysUnlock(); +} + +/** + * @brief Enforces leaving the sleep mode. + * @note The sleep mode is supposed to be usually exited automatically by + * an hardware event. + * + * @param[in] canp pointer to the @p CANDriver object + */ +void canWakeup(CANDriver *canp) { + + osalDbgCheck(canp != NULL); + + osalSysLock(); + osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), + "canWakeup(), #1", "invalid state"); + if (canp->state == CAN_SLEEP) { + can_lld_wakeup(canp); + canp->state = CAN_READY; + osalEventBroadcastFlagsI(&canp->wakeup_event, 0); + osalOsRescheduleS(); + } + osalSysUnlock(); +} +#endif /* CAN_USE_SLEEP_MODE */ + +#endif /* HAL_USE_CAN */ + +/** @} */ diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c new file mode 100644 index 000000000..8b56b4ac8 --- /dev/null +++ b/os/hal/src/hal.c @@ -0,0 +1,132 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file hal.c + * @brief HAL subsystem code. + * + * @addtogroup HAL + * @{ + */ + +#include "hal.h" + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief HAL initialization. + * @details This function invokes the low level initialization code then + * initializes all the drivers enabled in the HAL. Finally the + * board-specific initialization is performed by invoking + * @p boardInit() (usually defined in @p board.c). + * + * @init + */ +void halInit(void) { + + /* Initializes the OS Abstraction Layer.*/ + osalInit(); + + /* Platform low level initializations.*/ + hal_lld_init(); + +#if HAL_USE_TM || defined(__DOXYGEN__) + tmInit(); +#endif +#if HAL_USE_PAL || defined(__DOXYGEN__) + palInit(&pal_default_config); +#endif +#if HAL_USE_ADC || defined(__DOXYGEN__) + adcInit(); +#endif +#if HAL_USE_CAN || defined(__DOXYGEN__) + canInit(); +#endif +#if HAL_USE_EXT || defined(__DOXYGEN__) + extInit(); +#endif +#if HAL_USE_GPT || defined(__DOXYGEN__) + gptInit(); +#endif +#if HAL_USE_I2C || defined(__DOXYGEN__) + i2cInit(); +#endif +#if HAL_USE_ICU || defined(__DOXYGEN__) + icuInit(); +#endif +#if HAL_USE_MAC || defined(__DOXYGEN__) + macInit(); +#endif +#if HAL_USE_PWM || defined(__DOXYGEN__) + pwmInit(); +#endif +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + sdInit(); +#endif +#if HAL_USE_SDC || defined(__DOXYGEN__) + sdcInit(); +#endif +#if HAL_USE_SPI || defined(__DOXYGEN__) + spiInit(); +#endif +#if HAL_USE_UART || defined(__DOXYGEN__) + uartInit(); +#endif +#if HAL_USE_USB || defined(__DOXYGEN__) + usbInit(); +#endif +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) + mmcInit(); +#endif +#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) + sduInit(); +#endif +#if HAL_USE_RTC || defined(__DOXYGEN__) + rtcInit(); +#endif + + /* Board specific initialization.*/ + boardInit(); + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + /* System tick service if the underlying OS requires it.*/ + stInit(); +#endif +} + +/** @} */ diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c new file mode 100644 index 000000000..36016a1e9 --- /dev/null +++ b/os/hal/src/hal_queues.c @@ -0,0 +1,402 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file hal_queues.c + * @brief I/O Queues code. + * + * @addtogroup io_queues + * @details ChibiOS/RT queues are mostly used in serial-like device drivers. + * The device drivers are usually designed to have a lower side + * (lower driver, it is usually an interrupt service routine) and an + * upper side (upper driver, accessed by the application threads).
+ * There are several kind of queues:
+ * - Input queue, unidirectional queue where the writer is the + * lower side and the reader is the upper side. + * - Output queue, unidirectional queue where the writer is the + * upper side and the reader is the lower side. + * - Full duplex queue, bidirectional queue. Full duplex queues + * are implemented by pairing an input queue and an output queue + * together. + * . + * @{ + */ + +#include "hal.h" + +#if !defined(_CHIBIOS_RT_) || !CH_USE_QUEUES || defined(__DOXYGEN__) + +/** + * @brief Initializes an input queue. + * @details A Semaphore is internally initialized and works as a counter of + * the bytes contained in the queue. + * @note The callback is invoked from within the S-Locked system state, + * see @ref system_states. + * + * @param[out] iqp pointer to an @p InputQueue structure + * @param[in] bp pointer to a memory area allocated as queue buffer + * @param[in] size size of the queue buffer + * @param[in] infy pointer to a callback function that is invoked when + * data is read from the queue. The value can be @p NULL. + * @param[in] link application defined pointer + * + * @init + */ +void iqInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy, + void *link) { + + osalQueueObjectInit(&iqp->q_waiting); + iqp->q_counter = 0; + iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp; + iqp->q_top = bp + size; + iqp->q_notify = infy; + iqp->q_link = link; +} + +/** + * @brief Resets an input queue. + * @details All the data in the input queue is erased and lost, any waiting + * thread is resumed with status @p Q_RESET. + * @note A reset operation can be used by a low level driver in order to + * obtain immediate attention from the high level layers. + * + * @param[in] iqp pointer to an @p InputQueue structure + * + * @iclass + */ +void iqResetI(InputQueue *iqp) { + + osalDbgCheckClassI(); + + iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; + iqp->q_counter = 0; + osalQueueWakeupAllI(&iqp->q_waiting, Q_RESET); +} + +/** + * @brief Input queue write. + * @details A byte value is written into the low end of an input queue. + * + * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] b the byte value to be written in the queue + * @return The operation status. + * @retval Q_OK if the operation has been completed with success. + * @retval Q_FULL if the queue is full and the operation cannot be + * completed. + * + * @iclass + */ +msg_t iqPutI(InputQueue *iqp, uint8_t b) { + + osalDbgCheckClassI(); + + if (iqIsFullI(iqp)) + return Q_FULL; + + iqp->q_counter++; + *iqp->q_wrptr++ = b; + if (iqp->q_wrptr >= iqp->q_top) + iqp->q_wrptr = iqp->q_buffer; + + osalQueueWakeupOneI(&iqp->q_waiting, Q_OK); + + return Q_OK; +} + +/** + * @brief Input queue read with timeout. + * @details This function reads a byte value from an input queue. If the queue + * is empty then the calling thread is suspended until a byte arrives + * in the queue or a timeout occurs. + * @note The callback is invoked before reading the character from the + * buffer or before entering the state @p THD_STATE_WTQUEUE. + * + * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return A byte value from the queue. + * @retval Q_TIMEOUT if the specified time expired. + * @retval Q_RESET if the queue has been reset. + * + * @api + */ +msg_t iqGetTimeout(InputQueue *iqp, systime_t time) { + uint8_t b; + + osalSysLock(); + if (iqp->q_notify) + iqp->q_notify(iqp); + + while (iqIsEmptyI(iqp)) { + msg_t msg; + if ((msg = osalQueueGoSleepTimeoutS(&iqp->q_waiting, time)) < Q_OK) { + osalSysUnlock(); + return msg; + } + } + + iqp->q_counter--; + b = *iqp->q_rdptr++; + if (iqp->q_rdptr >= iqp->q_top) + iqp->q_rdptr = iqp->q_buffer; + + osalSysUnlock(); + return b; +} + +/** + * @brief Input queue read with timeout. + * @details The function reads data from an input queue into a buffer. The + * operation completes when the specified amount of data has been + * transferred or after the specified timeout or if the queue has + * been reset. + * @note The function is not atomic, if you need atomicity it is suggested + * to use a semaphore or a mutex for mutual exclusion. + * @note The callback is invoked before reading each character from the + * buffer or before entering the state @p THD_STATE_WTQUEUE. + * + * @param[in] iqp pointer to an @p InputQueue structure + * @param[out] bp pointer to the data buffer + * @param[in] n the maximum amount of data to be transferred, the + * value 0 is reserved + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The number of bytes effectively transferred. + * + * @api + */ +size_t iqReadTimeout(InputQueue *iqp, uint8_t *bp, + size_t n, systime_t time) { + qnotify_t nfy = iqp->q_notify; + size_t r = 0; + + osalDbgCheck(n > 0); + + osalSysLock(); + while (TRUE) { + if (nfy) + nfy(iqp); + + while (iqIsEmptyI(iqp)) { + if (osalQueueGoSleepTimeoutS(&iqp->q_waiting, time) != Q_OK) { + osalSysUnlock(); + return r; + } + } + + iqp->q_counter--; + *bp++ = *iqp->q_rdptr++; + if (iqp->q_rdptr >= iqp->q_top) + iqp->q_rdptr = iqp->q_buffer; + + osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ + r++; + if (--n == 0) + return r; + + osalSysLock(); + } +} + +/** + * @brief Initializes an output queue. + * @details A Semaphore is internally initialized and works as a counter of + * the free bytes in the queue. + * @note The callback is invoked from within the S-Locked system state, + * see @ref system_states. + * + * @param[out] oqp pointer to an @p OutputQueue structure + * @param[in] bp pointer to a memory area allocated as queue buffer + * @param[in] size size of the queue buffer + * @param[in] onfy pointer to a callback function that is invoked when + * data is written to the queue. The value can be @p NULL. + * @param[in] link application defined pointer + * + * @init + */ +void oqInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy, + void *link) { + + osalQueueObjectInit(&oqp->q_waiting); + oqp->q_counter = size; + oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp; + oqp->q_top = bp + size; + oqp->q_notify = onfy; + oqp->q_link = link; +} + +/** + * @brief Resets an output queue. + * @details All the data in the output queue is erased and lost, any waiting + * thread is resumed with status @p Q_RESET. + * @note A reset operation can be used by a low level driver in order to + * obtain immediate attention from the high level layers. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * + * @iclass + */ +void oqResetI(OutputQueue *oqp) { + + osalDbgCheckClassI(); + + oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; + oqp->q_counter = qSizeI(oqp); + osalQueueWakeupAllI(&oqp->q_waiting, Q_RESET); +} + +/** + * @brief Output queue write with timeout. + * @details This function writes a byte value to an output queue. If the queue + * is full then the calling thread is suspended until there is space + * in the queue or a timeout occurs. + * @note The callback is invoked after writing the character into the + * buffer. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] b the byte value to be written in the queue + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval Q_OK if the operation succeeded. + * @retval Q_TIMEOUT if the specified time expired. + * @retval Q_RESET if the queue has been reset. + * + * @api + */ +msg_t oqPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) { + + osalSysLock(); + while (oqIsFullI(oqp)) { + msg_t msg; + + if ((msg = osalQueueGoSleepTimeoutS(&oqp->q_waiting, time)) < Q_OK) { + osalSysUnlock(); + return msg; + } + } + + oqp->q_counter--; + *oqp->q_wrptr++ = b; + if (oqp->q_wrptr >= oqp->q_top) + oqp->q_wrptr = oqp->q_buffer; + + if (oqp->q_notify) + oqp->q_notify(oqp); + + osalSysUnlock(); + return Q_OK; +} + +/** + * @brief Output queue read. + * @details A byte value is read from the low end of an output queue. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * @return The byte value from the queue. + * @retval Q_EMPTY if the queue is empty. + * + * @iclass + */ +msg_t oqGetI(OutputQueue *oqp) { + uint8_t b; + + osalDbgCheckClassI(); + + if (oqIsEmptyI(oqp)) + return Q_EMPTY; + + oqp->q_counter++; + b = *oqp->q_rdptr++; + if (oqp->q_rdptr >= oqp->q_top) + oqp->q_rdptr = oqp->q_buffer; + + osalQueueWakeupOneI(&oqp->q_waiting, Q_OK); + + return b; +} + +/** + * @brief Output queue write with timeout. + * @details The function writes data from a buffer to an output queue. The + * operation completes when the specified amount of data has been + * transferred or after the specified timeout or if the queue has + * been reset. + * @note The function is not atomic, if you need atomicity it is suggested + * to use a semaphore or a mutex for mutual exclusion. + * @note The callback is invoked after writing each character into the + * buffer. + * + * @param[in] oqp pointer to an @p OutputQueue structure + * @param[out] bp pointer to the data buffer + * @param[in] n the maximum amount of data to be transferred, the + * value 0 is reserved + * @param[in] time the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_IMMEDIATE immediate timeout. + * - @a TIME_INFINITE no timeout. + * . + * @return The number of bytes effectively transferred. + * + * @api + */ +size_t oqWriteTimeout(OutputQueue *oqp, const uint8_t *bp, + size_t n, systime_t time) { + qnotify_t nfy = oqp->q_notify; + size_t w = 0; + + osalDbgCheck(n > 0); + + osalSysLock(); + while (TRUE) { + while (oqIsFullI(oqp)) { + if (osalQueueGoSleepTimeoutS(&oqp->q_waiting, time) != Q_OK) { + osalSysUnlock(); + return w; + } + } + oqp->q_counter--; + *oqp->q_wrptr++ = *bp++; + if (oqp->q_wrptr >= oqp->q_top) + oqp->q_wrptr = oqp->q_buffer; + + if (nfy) + nfy(oqp); + + osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ + w++; + if (--n == 0) + return w; + osalSysLock(); + } +} + +#endif /* !defined(_CHIBIOS_RT_) || !CH_USE_QUEUES */ + +/** @} */ diff --git a/os/hal/src/icu.c b/os/hal/src/icu.c new file mode 100644 index 000000000..401c0e04c --- /dev/null +++ b/os/hal/src/icu.c @@ -0,0 +1,158 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file icu.c + * @brief ICU Driver code. + * + * @addtogroup ICU + * @{ + */ + +#include "hal.h" + +#if HAL_USE_ICU || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ICU Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void icuInit(void) { + + icu_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p ICUDriver structure. + * + * @param[out] icup pointer to the @p ICUDriver object + * + * @init + */ +void icuObjectInit(ICUDriver *icup) { + + icup->state = ICU_STOP; + icup->config = NULL; +} + +/** + * @brief Configures and activates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * @param[in] config pointer to the @p ICUConfig object + * + * @api + */ +void icuStart(ICUDriver *icup, const ICUConfig *config) { + + osalDbgCheck((icup != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), + "icuStart(), #1", "invalid state"); + icup->config = config; + icu_lld_start(icup); + icup->state = ICU_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the ICU peripheral. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuStop(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), + "icuStop(), #1", "invalid state"); + icu_lld_stop(icup); + icup->state = ICU_STOP; + osalSysUnlock(); +} + +/** + * @brief Enables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuEnable(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert(icup->state == ICU_READY, "icuEnable(), #1", "invalid state"); + icu_lld_enable(icup); + icup->state = ICU_WAITING; + osalSysUnlock(); +} + +/** + * @brief Disables the input capture. + * + * @param[in] icup pointer to the @p ICUDriver object + * + * @api + */ +void icuDisable(ICUDriver *icup) { + + osalDbgCheck(icup != NULL); + + osalSysLock(); + osalDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) || + (icup->state == ICU_ACTIVE) || (icup->state == ICU_IDLE), + "icuDisable(), #1", "invalid state"); + icu_lld_disable(icup); + icup->state = ICU_READY; + osalSysUnlock(); +} + +#endif /* HAL_USE_ICU */ + +/** @} */ diff --git a/os/hal/src/pal.c b/os/hal/src/pal.c new file mode 100644 index 000000000..c2eb50a85 --- /dev/null +++ b/os/hal/src/pal.c @@ -0,0 +1,123 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file pal.c + * @brief I/O Ports Abstraction Layer code. + * + * @addtogroup PAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Read from an I/O bus. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p chSysLock() and + * @p chSysUnlock(). + * @note The function internally uses the @p palReadGroup() macro. The use + * of this function is preferred when you value code size, readability + * and error checking over speed. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @return The bus logical states. + * + * @api + */ +ioportmask_t palReadBus(IOBus *bus) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + return palReadGroup(bus->portid, bus->mask, bus->offset); +} + +/** + * @brief Write to an I/O bus. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p chSysLock() and + * @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] bits the bits to be written on the I/O bus. Values exceeding + * the bus width are masked so most significant bits are + * lost. + * + * @api + */ +void palWriteBus(IOBus *bus, ioportmask_t bits) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + palWriteGroup(bus->portid, bus->mask, bus->offset, bits); +} + +/** + * @brief Programs a bus with the specified mode. + * @note The operation is not guaranteed to be atomic on all the + * architectures, for atomicity and/or portability reasons you may + * need to enclose port I/O operations between @p chSysLock() and + * @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] mode the mode + * + * @api + */ +void palSetBusMode(IOBus *bus, iomode_t mode) { + + osalDbgCheck((bus != NULL) && (bus->offset < PAL_IOPORTS_WIDTH)); + + palSetGroupMode(bus->portid, bus->mask, bus->offset, mode); +} + +#endif /* HAL_USE_PAL */ + +/** @} */ diff --git a/os/hal/src/pwm.c b/os/hal/src/pwm.c new file mode 100644 index 000000000..bde512176 --- /dev/null +++ b/os/hal/src/pwm.c @@ -0,0 +1,204 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file pwm.c + * @brief PWM Driver code. + * + * @addtogroup PWM + * @{ + */ + +#include "hal.h" + +#if HAL_USE_PWM || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief PWM Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void pwmInit(void) { + + pwm_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p PWMDriver structure. + * + * @param[out] pwmp pointer to a @p PWMDriver object + * + * @init + */ +void pwmObjectInit(PWMDriver *pwmp) { + + pwmp->state = PWM_STOP; + pwmp->config = NULL; +#if defined(PWM_DRIVER_EXT_INIT_HOOK) + PWM_DRIVER_EXT_INIT_HOOK(pwmp); +#endif +} + +/** + * @brief Configures and activates the PWM peripheral. + * @note Starting a driver that is already in the @p PWM_READY state + * disables all the active channels. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] config pointer to a @p PWMConfig object + * + * @api + */ +void pwmStart(PWMDriver *pwmp, const PWMConfig *config) { + + osalDbgCheck((pwmp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), + "pwmStart(), #1", "invalid state"); + pwmp->config = config; + pwmp->period = config->period; + pwm_lld_start(pwmp); + pwmp->state = PWM_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the PWM peripheral. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * + * @api + */ +void pwmStop(PWMDriver *pwmp) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), + "pwmStop(), #1", "invalid state"); + pwm_lld_stop(pwmp); + pwmp->state = PWM_STOP; + osalSysUnlock(); +} + +/** + * @brief Changes the period the PWM peripheral. + * @details This function changes the period of a PWM unit that has already + * been activated using @p pwmStart(). + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The PWM unit period is changed to the new value. + * @note If a period is specified that is shorter than the pulse width + * programmed in one of the channels then the behavior is not + * guaranteed. + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] period new cycle time in ticks + * + * @api + */ +void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) { + + osalDbgCheck(pwmp != NULL); + + osalSysLock(); + osalDbgAssert(pwmp->state == PWM_READY, + "pwmChangePeriod(), #1", "invalid state"); + pwmChangePeriodI(pwmp, period); + osalSysUnlock(); +} + +/** + * @brief Enables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is active using the specified configuration. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * @param[in] width PWM pulse width as clock pulses number + * + * @api + */ +void pwmEnableChannel(PWMDriver *pwmp, + pwmchannel_t channel, + pwmcnt_t width) { + + osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS)); + + osalSysLock(); + osalDbgAssert(pwmp->state == PWM_READY, + "pwmEnableChannel(), #1", "not ready"); + pwm_lld_enable_channel(pwmp, channel, width); + osalSysUnlock(); +} + +/** + * @brief Disables a PWM channel. + * @pre The PWM unit must have been activated using @p pwmStart(). + * @post The channel is disabled and its output line returned to the + * idle state. + * @note Depending on the hardware implementation this function has + * effect starting on the next cycle (recommended implementation) + * or immediately (fallback implementation). + * + * @param[in] pwmp pointer to a @p PWMDriver object + * @param[in] channel PWM channel identifier (0...PWM_CHANNELS-1) + * + * @api + */ +void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { + + osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS)); + + osalSysLock(); + osalDbgAssert(pwmp->state == PWM_READY, + "pwmDisableChannel(), #1", "not ready"); + pwm_lld_disable_channel(pwmp, channel); + osalSysUnlock(); +} + +#endif /* HAL_USE_PWM */ + +/** @} */ diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c new file mode 100644 index 000000000..73a0b7457 --- /dev/null +++ b/os/hal/src/serial.c @@ -0,0 +1,243 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file serial.c + * @brief Serial Driver code. + * + * @addtogroup SERIAL + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/* + * Interface implementation, the following functions just invoke the equivalent + * queue-level function or macro. + */ + +static size_t write(void *ip, const uint8_t *bp, size_t n) { + + return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, + n, TIME_INFINITE); +} + +static size_t read(void *ip, uint8_t *bp, size_t n) { + + return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, + n, TIME_INFINITE); +} + +static msg_t put(void *ip, uint8_t b) { + + return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE); +} + +static msg_t get(void *ip) { + + return iqGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE); +} + +static msg_t putt(void *ip, uint8_t b, systime_t timeout) { + + return oqPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout); +} + +static msg_t gett(void *ip, systime_t timeout) { + + return iqGetTimeout(&((SerialDriver *)ip)->iqueue, timeout); +} + +static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { + + return oqWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, time); +} + +static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { + + return iqReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, time); +} + +static const struct SerialDriverVMT vmt = { + write, read, put, get, + putt, gett, writet, readt +}; + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Serial Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sdInit(void) { + + sd_lld_init(); +} + +/** + * @brief Initializes a generic full duplex driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] sdp pointer to a @p SerialDriver structure + * @param[in] inotify pointer to a callback function that is invoked when + * some data is read from the Queue. The value can be + * @p NULL. + * @param[in] onotify pointer to a callback function that is invoked when + * some data is written in the Queue. The value can be + * @p NULL. + * + * @init + */ +void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { + + sdp->vmt = &vmt; + osalEventObjectInit(&sdp->event); + sdp->state = SD_STOP; + iqInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); + oqInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); +} + +/** + * @brief Configures and starts the driver. + * + * @param[in] sdp pointer to a @p SerialDriver object + * @param[in] config the architecture-dependent serial driver configuration. + * If this parameter is set to @p NULL then a default + * configuration is used. + * + * @api + */ +void sdStart(SerialDriver *sdp, const SerialConfig *config) { + + osalDbgCheck(sdp != NULL); + + osalSysLock(); + osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), + "sdStart(), #1", "invalid state"); + sd_lld_start(sdp, config); + sdp->state = SD_READY; + osalSysUnlock(); +} + +/** + * @brief Stops the driver. + * @details Any thread waiting on the driver's queues will be awakened with + * the message @p Q_RESET. + * + * @param[in] sdp pointer to a @p SerialDriver object + * + * @api + */ +void sdStop(SerialDriver *sdp) { + + osalDbgCheck(sdp != NULL); + + osalSysLock(); + osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), + "sdStop(), #1", "invalid state"); + sd_lld_stop(sdp); + sdp->state = SD_STOP; + oqResetI(&sdp->oqueue); + iqResetI(&sdp->iqueue); + osalOsRescheduleS(); + osalSysUnlock(); +} + +/** + * @brief Handles incoming data. + * @details This function must be called from the input interrupt service + * routine in order to enqueue incoming data and generate the + * related events. + * @note The incoming data event is only generated when the input queue + * becomes non-empty. + * @note In order to gain some performance it is suggested to not use + * this function directly but copy this code directly into the + * interrupt service routine. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @param[in] b the byte to be written in the driver's Input Queue + * + * @iclass + */ +void sdIncomingDataI(SerialDriver *sdp, uint8_t b) { + + osalDbgCheckClassI(); + osalDbgCheck(sdp != NULL); + + if (iqIsEmptyI(&sdp->iqueue)) + chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE); + if (iqPutI(&sdp->iqueue, b) < Q_OK) + chnAddFlagsI(sdp, SD_OVERRUN_ERROR); +} + +/** + * @brief Handles outgoing data. + * @details Must be called from the output interrupt service routine in order + * to get the next byte to be transmitted. + * @note In order to gain some performance it is suggested to not use + * this function directly but copy this code directly into the + * interrupt service routine. + * + * @param[in] sdp pointer to a @p SerialDriver structure + * @return The byte value read from the driver's output queue. + * @retval Q_EMPTY if the queue is empty (the lower driver usually + * disables the interrupt source when this happens). + * + * @iclass + */ +msg_t sdRequestDataI(SerialDriver *sdp) { + msg_t b; + + osalDbgCheckClassI(); + osalDbgCheck(sdp != NULL); + + b = oqGetI(&sdp->oqueue); + if (b < Q_OK) + chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY); + return b; +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c new file mode 100644 index 000000000..cd7124bd3 --- /dev/null +++ b/os/hal/src/spi.c @@ -0,0 +1,428 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file spi.c + * @brief SPI Driver code. + * + * @addtogroup SPI + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief SPI Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void spiInit(void) { + + spi_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SPIDriver structure. + * + * @param[out] spip pointer to the @p SPIDriver object + * + * @init + */ +void spiObjectInit(SPIDriver *spip) { + + spip->state = SPI_STOP; + spip->config = NULL; +#if SPI_USE_WAIT + spip->thread = NULL; +#endif /* SPI_USE_WAIT */ +#if SPI_USE_MUTUAL_EXCLUSION + osalMutexObjectInit(&spip->mutex); +#endif /* SPI_USE_MUTUAL_EXCLUSION */ +#if defined(SPI_DRIVER_EXT_INIT_HOOK) + SPI_DRIVER_EXT_INIT_HOOK(spip); +#endif +} + +/** + * @brief Configures and activates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] config pointer to the @p SPIConfig object + * + * @api + */ +void spiStart(SPIDriver *spip, const SPIConfig *config) { + + osalDbgCheck((spip != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), + "spiStart(), #1", "invalid state"); + spip->config = config; + spi_lld_start(spip); + spip->state = SPI_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the SPI peripheral. + * @note Deactivating the peripheral also enforces a release of the slave + * select line. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiStop(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), + "spiStop(), #1", "invalid state"); + spi_lld_stop(spip); + spip->state = SPI_STOP; + osalSysUnlock(); +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiSelect(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "spiSelect(), #1", "not ready"); + spiSelectI(spip); + osalSysUnlock(); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiUnselect(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "spiUnselect(), #1", "not ready"); + spiUnselectI(spip); + osalSysUnlock(); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This asynchronous function starts the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @api + */ +void spiStartIgnore(SPIDriver *spip, size_t n) { + + osalDbgCheck((spip != NULL) && (n > 0)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "spiStartIgnore(), #1", "not ready"); + spiStartIgnoreI(spip, n); + osalSysUnlock(); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This asynchronous function starts a simultaneous transmit/receive + * operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiStartExchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, + "spiStartExchange(), #1", "not ready"); + spiStartExchangeI(spip, n, txbuf, rxbuf); + osalSysUnlock(); +} + +/** + * @brief Sends data over the SPI bus. + * @details This asynchronous function starts a transmit operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "spiStartSend(), #1", "not ready"); + spiStartSendI(spip, n, txbuf); + osalSysUnlock(); +} + +/** + * @brief Receives data from the SPI bus. + * @details This asynchronous function starts a receive operation. + * @pre A slave must have been selected using @p spiSelect() or + * @p spiSelectI(). + * @post At the end of the operation the configured callback is invoked. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, + "spiStartReceive(), #1", "not ready"); + spiStartReceiveI(spip, n, rxbuf); + osalSysUnlock(); +} + +#if SPI_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Ignores data on the SPI bus. + * @details This synchronous function performs the transmission of a series of + * idle words on the SPI bus and ignores the received data. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + * + * @api + */ +void spiIgnore(SPIDriver *spip, size_t n) { + + osalDbgCheck((spip != NULL) && (n > 0)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, + "spiIgnore(), #1", "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, + "spiIgnore(), #2", "has callback"); + spiStartIgnoreI(spip, n); + _spi_wait_s(spip); + osalSysUnlock(); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This synchronous function performs a simultaneous transmit/receive + * operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be exchanged + * @param[in] txbuf the pointer to the transmit buffer + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiExchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && + (rxbuf != NULL) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, "spiExchange(), #1", "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, + "spiExchange(), #2", "has callback"); + spiStartExchangeI(spip, n, txbuf, rxbuf); + _spi_wait_s(spip); + osalSysUnlock(); +} + +/** + * @brief Sends data over the SPI bus. + * @details This synchronous function performs a transmit operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, + "spiSend(), #1", "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, + "spiSend(), #2", "has callback"); + spiStartSendI(spip, n, txbuf); + _spi_wait_s(spip); + osalSysUnlock(); +} + +/** + * @brief Receives data from the SPI bus. + * @details This synchronous function performs a receive operation. + * @pre In order to use this function the option @p SPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to receive + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { + + osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(spip->state == SPI_READY, + "spiReceive(), #1", "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, + "spiReceive(), #2", "has callback"); + spiStartReceiveI(spip, n, rxbuf); + _spi_wait_s(spip); + osalSysUnlock(); +} +#endif /* SPI_USE_WAIT */ + +#if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the SPI bus. + * @details This function tries to gain ownership to the SPI bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiAcquireBus(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalMutexLock(&spip->mutex); +} + +/** + * @brief Releases exclusive access to the SPI bus. + * @pre In order to use this function the option @p SPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spiReleaseBus(SPIDriver *spip) { + + osalDbgCheck(spip != NULL); + + osalMutexUnlock(&spip->mutex); +} +#endif /* SPI_USE_MUTUAL_EXCLUSION */ + +#endif /* HAL_USE_SPI */ + +/** @} */ diff --git a/os/hal/src/st.c b/os/hal/src/st.c new file mode 100644 index 000000000..f2e8f3bf2 --- /dev/null +++ b/os/hal/src/st.c @@ -0,0 +1,71 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file st.c + * @brief ST Driver code. + * + * @addtogroup ST + * @{ + */ + +#include "hal.h" + +#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief ST Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void stInit(void) { + + st_lld_init(); +} + +#endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ + +/** @} */ -- cgit v1.2.3 From 8576e8da6ab76f07fb877b89f0a3e6afc9bced0c Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Aug 2013 12:57:40 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6111 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_queues.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c index 36016a1e9..5a4465652 100644 --- a/os/hal/src/hal_queues.c +++ b/os/hal/src/hal_queues.c @@ -41,7 +41,7 @@ #include "hal.h" -#if !defined(_CHIBIOS_RT_) || !CH_USE_QUEUES || defined(__DOXYGEN__) +#if !defined(_CHIBIOS_RT_) || !CH_CFG_USE_QUEUES || defined(__DOXYGEN__) /** * @brief Initializes an input queue. -- cgit v1.2.3 From 7b51712449ffa10f260f60e6968257230fe63f15 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Aug 2013 13:43:56 +0000 Subject: Updated queues. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6112 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_queues.c | 8 ++++---- os/hal/src/serial.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c index 5a4465652..71330854e 100644 --- a/os/hal/src/hal_queues.c +++ b/os/hal/src/hal_queues.c @@ -59,8 +59,8 @@ * * @init */ -void iqInit(InputQueue *iqp, uint8_t *bp, size_t size, qnotify_t infy, - void *link) { +void iqObjectInit(InputQueue *iqp, uint8_t *bp, size_t size, + qnotify_t infy, void *link) { osalQueueObjectInit(&iqp->q_waiting); iqp->q_counter = 0; @@ -237,8 +237,8 @@ size_t iqReadTimeout(InputQueue *iqp, uint8_t *bp, * * @init */ -void oqInit(OutputQueue *oqp, uint8_t *bp, size_t size, qnotify_t onfy, - void *link) { +void oqObjectInit(OutputQueue *oqp, uint8_t *bp, size_t size, + qnotify_t onfy, void *link) { osalQueueObjectInit(&oqp->q_waiting); oqp->q_counter = size; diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c index 73a0b7457..0b9d5b41d 100644 --- a/os/hal/src/serial.c +++ b/os/hal/src/serial.c @@ -134,8 +134,8 @@ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { sdp->vmt = &vmt; osalEventObjectInit(&sdp->event); sdp->state = SD_STOP; - iqInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); - oqInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); + iqObjectInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); + oqObjectInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); } /** -- cgit v1.2.3 From 44f6cc630876bfa5311b1c7e196a6ae5b5806b73 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 9 Aug 2013 13:56:40 +0000 Subject: HAL queues updated. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6113 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_queues.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c index 71330854e..89dc03911 100644 --- a/os/hal/src/hal_queues.c +++ b/os/hal/src/hal_queues.c @@ -50,7 +50,7 @@ * @note The callback is invoked from within the S-Locked system state, * see @ref system_states. * - * @param[out] iqp pointer to an @p InputQueue structure + * @param[out] iqp pointer to an @p input_queue_t structure * @param[in] bp pointer to a memory area allocated as queue buffer * @param[in] size size of the queue buffer * @param[in] infy pointer to a callback function that is invoked when @@ -59,7 +59,7 @@ * * @init */ -void iqObjectInit(InputQueue *iqp, uint8_t *bp, size_t size, +void iqObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size, qnotify_t infy, void *link) { osalQueueObjectInit(&iqp->q_waiting); @@ -77,11 +77,11 @@ void iqObjectInit(InputQueue *iqp, uint8_t *bp, size_t size, * @note A reset operation can be used by a low level driver in order to * obtain immediate attention from the high level layers. * - * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] iqp pointer to an @p input_queue_t structure * * @iclass */ -void iqResetI(InputQueue *iqp) { +void iqResetI(input_queue_t *iqp) { osalDbgCheckClassI(); @@ -94,7 +94,7 @@ void iqResetI(InputQueue *iqp) { * @brief Input queue write. * @details A byte value is written into the low end of an input queue. * - * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] iqp pointer to an @p input_queue_t structure * @param[in] b the byte value to be written in the queue * @return The operation status. * @retval Q_OK if the operation has been completed with success. @@ -103,7 +103,7 @@ void iqResetI(InputQueue *iqp) { * * @iclass */ -msg_t iqPutI(InputQueue *iqp, uint8_t b) { +msg_t iqPutI(input_queue_t *iqp, uint8_t b) { osalDbgCheckClassI(); @@ -128,7 +128,7 @@ msg_t iqPutI(InputQueue *iqp, uint8_t b) { * @note The callback is invoked before reading the character from the * buffer or before entering the state @p THD_STATE_WTQUEUE. * - * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] iqp pointer to an @p input_queue_t structure * @param[in] time the number of ticks before the operation timeouts, * the following special values are allowed: * - @a TIME_IMMEDIATE immediate timeout. @@ -140,7 +140,7 @@ msg_t iqPutI(InputQueue *iqp, uint8_t b) { * * @api */ -msg_t iqGetTimeout(InputQueue *iqp, systime_t time) { +msg_t iqGetTimeout(input_queue_t *iqp, systime_t time) { uint8_t b; osalSysLock(); @@ -175,7 +175,7 @@ msg_t iqGetTimeout(InputQueue *iqp, systime_t time) { * @note The callback is invoked before reading each character from the * buffer or before entering the state @p THD_STATE_WTQUEUE. * - * @param[in] iqp pointer to an @p InputQueue structure + * @param[in] iqp pointer to an @p input_queue_t structure * @param[out] bp pointer to the data buffer * @param[in] n the maximum amount of data to be transferred, the * value 0 is reserved @@ -188,8 +188,8 @@ msg_t iqGetTimeout(InputQueue *iqp, systime_t time) { * * @api */ -size_t iqReadTimeout(InputQueue *iqp, uint8_t *bp, - size_t n, systime_t time) { +size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp, + size_t n, systime_t time) { qnotify_t nfy = iqp->q_notify; size_t r = 0; @@ -228,7 +228,7 @@ size_t iqReadTimeout(InputQueue *iqp, uint8_t *bp, * @note The callback is invoked from within the S-Locked system state, * see @ref system_states. * - * @param[out] oqp pointer to an @p OutputQueue structure + * @param[out] oqp pointer to an @p output_queue_t structure * @param[in] bp pointer to a memory area allocated as queue buffer * @param[in] size size of the queue buffer * @param[in] onfy pointer to a callback function that is invoked when @@ -237,7 +237,7 @@ size_t iqReadTimeout(InputQueue *iqp, uint8_t *bp, * * @init */ -void oqObjectInit(OutputQueue *oqp, uint8_t *bp, size_t size, +void oqObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size, qnotify_t onfy, void *link) { osalQueueObjectInit(&oqp->q_waiting); @@ -255,11 +255,11 @@ void oqObjectInit(OutputQueue *oqp, uint8_t *bp, size_t size, * @note A reset operation can be used by a low level driver in order to * obtain immediate attention from the high level layers. * - * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] oqp pointer to an @p output_queue_t structure * * @iclass */ -void oqResetI(OutputQueue *oqp) { +void oqResetI(output_queue_t *oqp) { osalDbgCheckClassI(); @@ -276,7 +276,7 @@ void oqResetI(OutputQueue *oqp) { * @note The callback is invoked after writing the character into the * buffer. * - * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] oqp pointer to an @p output_queue_t structure * @param[in] b the byte value to be written in the queue * @param[in] time the number of ticks before the operation timeouts, * the following special values are allowed: @@ -290,7 +290,7 @@ void oqResetI(OutputQueue *oqp) { * * @api */ -msg_t oqPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) { +msg_t oqPutTimeout(output_queue_t *oqp, uint8_t b, systime_t time) { osalSysLock(); while (oqIsFullI(oqp)) { @@ -318,13 +318,13 @@ msg_t oqPutTimeout(OutputQueue *oqp, uint8_t b, systime_t time) { * @brief Output queue read. * @details A byte value is read from the low end of an output queue. * - * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] oqp pointer to an @p output_queue_t structure * @return The byte value from the queue. * @retval Q_EMPTY if the queue is empty. * * @iclass */ -msg_t oqGetI(OutputQueue *oqp) { +msg_t oqGetI(output_queue_t *oqp) { uint8_t b; osalDbgCheckClassI(); @@ -353,7 +353,7 @@ msg_t oqGetI(OutputQueue *oqp) { * @note The callback is invoked after writing each character into the * buffer. * - * @param[in] oqp pointer to an @p OutputQueue structure + * @param[in] oqp pointer to an @p output_queue_t structure * @param[out] bp pointer to the data buffer * @param[in] n the maximum amount of data to be transferred, the * value 0 is reserved @@ -366,8 +366,8 @@ msg_t oqGetI(OutputQueue *oqp) { * * @api */ -size_t oqWriteTimeout(OutputQueue *oqp, const uint8_t *bp, - size_t n, systime_t time) { +size_t oqWriteTimeout(output_queue_t *oqp, const uint8_t *bp, + size_t n, systime_t time) { qnotify_t nfy = oqp->q_notify; size_t w = 0; -- cgit v1.2.3 From eb7a1a15b23341693864c6fc13ac5eab5c1d6122 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 10 Aug 2013 14:50:32 +0000 Subject: Removed 2nd parameter to assertion and check macros. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6122 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/adc.c | 15 +++++++-------- os/hal/src/can.c | 12 ++++++------ os/hal/src/icu.c | 8 ++++---- os/hal/src/pwm.c | 13 +++++-------- os/hal/src/serial.c | 4 ++-- os/hal/src/spi.c | 41 ++++++++++++++++------------------------- 6 files changed, 40 insertions(+), 53 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/adc.c b/os/hal/src/adc.c index ccc11574a..e6d8d8075 100644 --- a/os/hal/src/adc.c +++ b/os/hal/src/adc.c @@ -102,7 +102,7 @@ void adcStart(ADCDriver *adcp, const ADCConfig *config) { osalSysLock(); osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "adcStart(), #1", "invalid state"); + "invalid state"); adcp->config = config; adc_lld_start(adcp); adcp->state = ADC_READY; @@ -122,7 +122,7 @@ void adcStop(ADCDriver *adcp) { osalSysLock(); osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY), - "adcStop(), #1", "invalid state"); + "invalid state"); adc_lld_stop(adcp); adcp->state = ADC_STOP; osalSysUnlock(); @@ -183,7 +183,7 @@ void adcStartConversionI(ADCDriver *adcp, osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_COMPLETE) || (adcp->state == ADC_ERROR), - "adcStartConversionI(), #1", "not ready"); + "not ready"); adcp->samples = samples; adcp->depth = depth; @@ -207,9 +207,8 @@ void adcStopConversion(ADCDriver *adcp) { osalDbgCheck(adcp != NULL); osalSysLock(); - osalDbgAssert((adcp->state == ADC_READY) || - (adcp->state == ADC_ACTIVE), - "adcStopConversion(), #1", "invalid state"); + osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE), + "invalid state"); if (adcp->state != ADC_READY) { adc_lld_stop_conversion(adcp); adcp->grpp = NULL; @@ -236,7 +235,7 @@ void adcStopConversionI(ADCDriver *adcp) { osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE) || (adcp->state == ADC_COMPLETE), - "adcStopConversionI(), #1", "invalid state"); + "invalid state"); if (adcp->state != ADC_READY) { adc_lld_stop_conversion(adcp); @@ -277,7 +276,7 @@ msg_t adcConvert(ADCDriver *adcp, msg_t msg; osalSysLock(); - osalDbgAssert(adcp->thread == NULL, "adcConvert(), #1", "already waiting"); + osalDbgAssert(adcp->thread == NULL, "already waiting"); adcStartConversionI(adcp, grpp, samples, depth); msg = osalThreadSuspendS(&adcp->thread); osalSysUnlock(); diff --git a/os/hal/src/can.c b/os/hal/src/can.c index 9a352ddd1..ed5c43f87 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -104,7 +104,7 @@ void canStart(CANDriver *canp, const CANConfig *config) { osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_STARTING) || (canp->state == CAN_READY), - "canStart(), #1", "invalid state"); + "invalid state"); while (canp->state == CAN_STARTING) osalThreadSleepS(1); if (canp->state == CAN_STOP) { @@ -128,7 +128,7 @@ void canStop(CANDriver *canp) { osalSysLock(); osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY), - "canStop(), #1", "invalid state"); + "invalid state"); can_lld_stop(canp); canp->state = CAN_STOP; osalQueueWakeupAllI(&canp->rxqueue, MSG_RESET); @@ -168,7 +168,7 @@ msg_t canTransmit(CANDriver *canp, osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canTransmit(), #1", "invalid state"); + "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { msg_t msg = osalQueueGoSleepTimeoutS(&canp->txqueue, timeout); if (msg != MSG_OK) { @@ -213,7 +213,7 @@ msg_t canReceive(CANDriver *canp, osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canReceive(), #1", "invalid state"); + "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { msg_t msg = osalQueueGoSleepTimeoutS(&canp->rxqueue, timeout); if (msg != MSG_OK) { @@ -245,7 +245,7 @@ void canSleep(CANDriver *canp) { osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canSleep(), #1", "invalid state"); + "invalid state"); if (canp->state == CAN_READY) { can_lld_sleep(canp); canp->state = CAN_SLEEP; @@ -268,7 +268,7 @@ void canWakeup(CANDriver *canp) { osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), - "canWakeup(), #1", "invalid state"); + "invalid state"); if (canp->state == CAN_SLEEP) { can_lld_wakeup(canp); canp->state = CAN_READY; diff --git a/os/hal/src/icu.c b/os/hal/src/icu.c index 401c0e04c..291b6df9a 100644 --- a/os/hal/src/icu.c +++ b/os/hal/src/icu.c @@ -89,7 +89,7 @@ void icuStart(ICUDriver *icup, const ICUConfig *config) { osalSysLock(); osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "icuStart(), #1", "invalid state"); + "invalid state"); icup->config = config; icu_lld_start(icup); icup->state = ICU_READY; @@ -109,7 +109,7 @@ void icuStop(ICUDriver *icup) { osalSysLock(); osalDbgAssert((icup->state == ICU_STOP) || (icup->state == ICU_READY), - "icuStop(), #1", "invalid state"); + "invalid state"); icu_lld_stop(icup); icup->state = ICU_STOP; osalSysUnlock(); @@ -127,7 +127,7 @@ void icuEnable(ICUDriver *icup) { osalDbgCheck(icup != NULL); osalSysLock(); - osalDbgAssert(icup->state == ICU_READY, "icuEnable(), #1", "invalid state"); + osalDbgAssert(icup->state == ICU_READY, "invalid state"); icu_lld_enable(icup); icup->state = ICU_WAITING; osalSysUnlock(); @@ -147,7 +147,7 @@ void icuDisable(ICUDriver *icup) { osalSysLock(); osalDbgAssert((icup->state == ICU_READY) || (icup->state == ICU_WAITING) || (icup->state == ICU_ACTIVE) || (icup->state == ICU_IDLE), - "icuDisable(), #1", "invalid state"); + "invalid state"); icu_lld_disable(icup); icup->state = ICU_READY; osalSysUnlock(); diff --git a/os/hal/src/pwm.c b/os/hal/src/pwm.c index bde512176..dfbe32df3 100644 --- a/os/hal/src/pwm.c +++ b/os/hal/src/pwm.c @@ -94,7 +94,7 @@ void pwmStart(PWMDriver *pwmp, const PWMConfig *config) { osalSysLock(); osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "pwmStart(), #1", "invalid state"); + "invalid state"); pwmp->config = config; pwmp->period = config->period; pwm_lld_start(pwmp); @@ -115,7 +115,7 @@ void pwmStop(PWMDriver *pwmp) { osalSysLock(); osalDbgAssert((pwmp->state == PWM_STOP) || (pwmp->state == PWM_READY), - "pwmStop(), #1", "invalid state"); + "invalid state"); pwm_lld_stop(pwmp); pwmp->state = PWM_STOP; osalSysUnlock(); @@ -141,8 +141,7 @@ void pwmChangePeriod(PWMDriver *pwmp, pwmcnt_t period) { osalDbgCheck(pwmp != NULL); osalSysLock(); - osalDbgAssert(pwmp->state == PWM_READY, - "pwmChangePeriod(), #1", "invalid state"); + osalDbgAssert(pwmp->state == PWM_READY, "invalid state"); pwmChangePeriodI(pwmp, period); osalSysUnlock(); } @@ -168,8 +167,7 @@ void pwmEnableChannel(PWMDriver *pwmp, osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS)); osalSysLock(); - osalDbgAssert(pwmp->state == PWM_READY, - "pwmEnableChannel(), #1", "not ready"); + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); pwm_lld_enable_channel(pwmp, channel, width); osalSysUnlock(); } @@ -193,8 +191,7 @@ void pwmDisableChannel(PWMDriver *pwmp, pwmchannel_t channel) { osalDbgCheck((pwmp != NULL) && (channel < PWM_CHANNELS)); osalSysLock(); - osalDbgAssert(pwmp->state == PWM_READY, - "pwmDisableChannel(), #1", "not ready"); + osalDbgAssert(pwmp->state == PWM_READY, "not ready"); pwm_lld_disable_channel(pwmp, channel); osalSysUnlock(); } diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c index 0b9d5b41d..4b1fd17d5 100644 --- a/os/hal/src/serial.c +++ b/os/hal/src/serial.c @@ -154,7 +154,7 @@ void sdStart(SerialDriver *sdp, const SerialConfig *config) { osalSysLock(); osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "sdStart(), #1", "invalid state"); + "invalid state"); sd_lld_start(sdp, config); sdp->state = SD_READY; osalSysUnlock(); @@ -175,7 +175,7 @@ void sdStop(SerialDriver *sdp) { osalSysLock(); osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY), - "sdStop(), #1", "invalid state"); + "invalid state"); sd_lld_stop(sdp); sdp->state = SD_STOP; oqResetI(&sdp->oqueue); diff --git a/os/hal/src/spi.c b/os/hal/src/spi.c index cd7124bd3..f47ed0527 100644 --- a/os/hal/src/spi.c +++ b/os/hal/src/spi.c @@ -98,7 +98,7 @@ void spiStart(SPIDriver *spip, const SPIConfig *config) { osalSysLock(); osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "spiStart(), #1", "invalid state"); + "invalid state"); spip->config = config; spi_lld_start(spip); spip->state = SPI_READY; @@ -120,7 +120,7 @@ void spiStop(SPIDriver *spip) { osalSysLock(); osalDbgAssert((spip->state == SPI_STOP) || (spip->state == SPI_READY), - "spiStop(), #1", "invalid state"); + "invalid state"); spi_lld_stop(spip); spip->state = SPI_STOP; osalSysUnlock(); @@ -138,7 +138,7 @@ void spiSelect(SPIDriver *spip) { osalDbgCheck(spip != NULL); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "spiSelect(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiSelectI(spip); osalSysUnlock(); } @@ -156,7 +156,7 @@ void spiUnselect(SPIDriver *spip) { osalDbgCheck(spip != NULL); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "spiUnselect(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiUnselectI(spip); osalSysUnlock(); } @@ -179,7 +179,7 @@ void spiStartIgnore(SPIDriver *spip, size_t n) { osalDbgCheck((spip != NULL) && (n > 0)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "spiStartIgnore(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiStartIgnoreI(spip, n); osalSysUnlock(); } @@ -207,8 +207,7 @@ void spiStartExchange(SPIDriver *spip, size_t n, osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, - "spiStartExchange(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiStartExchangeI(spip, n, txbuf, rxbuf); osalSysUnlock(); } @@ -233,7 +232,7 @@ void spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { osalDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "spiStartSend(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiStartSendI(spip, n, txbuf); osalSysUnlock(); } @@ -258,8 +257,7 @@ void spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, - "spiStartReceive(), #1", "not ready"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); spiStartReceiveI(spip, n, rxbuf); osalSysUnlock(); } @@ -284,10 +282,8 @@ void spiIgnore(SPIDriver *spip, size_t n) { osalDbgCheck((spip != NULL) && (n > 0)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, - "spiIgnore(), #1", "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, - "spiIgnore(), #2", "has callback"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); spiStartIgnoreI(spip, n); _spi_wait_s(spip); osalSysUnlock(); @@ -318,9 +314,8 @@ void spiExchange(SPIDriver *spip, size_t n, (rxbuf != NULL) && (txbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, "spiExchange(), #1", "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, - "spiExchange(), #2", "has callback"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); spiStartExchangeI(spip, n, txbuf, rxbuf); _spi_wait_s(spip); osalSysUnlock(); @@ -347,10 +342,8 @@ void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { osalDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, - "spiSend(), #1", "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, - "spiSend(), #2", "has callback"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); spiStartSendI(spip, n, txbuf); _spi_wait_s(spip); osalSysUnlock(); @@ -377,10 +370,8 @@ void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { osalDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL)); osalSysLock(); - osalDbgAssert(spip->state == SPI_READY, - "spiReceive(), #1", "not ready"); - osalDbgAssert(spip->config->end_cb == NULL, - "spiReceive(), #2", "has callback"); + osalDbgAssert(spip->state == SPI_READY, "not ready"); + osalDbgAssert(spip->config->end_cb == NULL, "has callback"); spiStartReceiveI(spip, n, rxbuf); _spi_wait_s(spip); osalSysUnlock(); -- cgit v1.2.3 From 78e314cdada1c3dba3078d3b8645f90687676bd9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 12 Aug 2013 16:01:07 +0000 Subject: Ported GPT. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6141 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/gpt.c | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 os/hal/src/gpt.c (limited to 'os/hal/src') diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c new file mode 100644 index 000000000..780ac407e --- /dev/null +++ b/os/hal/src/gpt.c @@ -0,0 +1,267 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file gpt.c + * @brief GPT Driver code. + * + * @addtogroup GPT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_GPT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief GPT Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void gptInit(void) { + + gpt_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p GPTDriver structure. + * + * @param[out] gptp pointer to the @p GPTDriver object + * + * @init + */ +void gptObjectInit(GPTDriver *gptp) { + + gptp->state = GPT_STOP; + gptp->config = NULL; +} + +/** + * @brief Configures and activates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] config pointer to the @p GPTConfig object + * + * @api + */ +void gptStart(GPTDriver *gptp, const GPTConfig *config) { + + osalDbgCheck((gptp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), + "invalid state"); + gptp->config = config; + gpt_lld_start(gptp); + gptp->state = GPT_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the GPT peripheral. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStop(GPTDriver *gptp) { + + osalDbgCheck(gptp != NULL); + + osalSysLock(); + osalDbgAssert((gptp->state == GPT_STOP) || (gptp->state == GPT_READY), + "invalid state"); + gpt_lld_stop(gptp); + gptp->state = GPT_STOP; + osalSysUnlock(); +} + +/** + * @brief Changes the interval of GPT peripheral. + * @details This function changes the interval of a running GPT unit. + * @pre The GPT unit must have been activated using @p gptStart(). + * @pre The GPT unit must have been running in continuous mode using + * @p gptStartContinuous(). + * @post The GPT unit interval is changed to the new value. + * + * @param[in] gptp pointer to a @p GPTDriver object + * @param[in] interval new cycle time in timer ticks + * + * @api + */ +void gptChangeInterval(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheck(gptp != NULL); + + osalSysLock(); + osalDbgAssert(gptp->state == GPT_CONTINUOUS, + "invalid state"); + gptChangeIntervalI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @api + */ +void gptStartContinuous(GPTDriver *gptp, gptcnt_t interval) { + + osalSysLock(); + gptStartContinuousI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in continuous mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval period in ticks + * + * @iclass + */ +void gptStartContinuousI(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_CONTINUOUS; + gpt_lld_start_timer(gptp, interval); +} + +/** + * @brief Starts the timer in one shot mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptStartOneShot(GPTDriver *gptp, gptcnt_t interval) { + + osalSysLock(); + gptStartOneShotI(gptp, interval); + osalSysUnlock(); +} + +/** + * @brief Starts the timer in one shot mode. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_ONESHOT; + gpt_lld_start_timer(gptp, interval); +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStopTimer(GPTDriver *gptp) { + + osalSysLock(); + gptStopTimerI(gptp); + osalSysUnlock(); +} + +/** + * @brief Stops the timer. + * + * @param[in] gptp pointer to the @p GPTDriver object + * + * @api + */ +void gptStopTimerI(GPTDriver *gptp) { + + osalDbgCheckClassI(); + osalDbgCheck(gptp != NULL); + osalDbgAssert((gptp->state == GPT_READY) || (gptp->state == GPT_CONTINUOUS) || + (gptp->state == GPT_ONESHOT), + "invalid state"); + + gptp->state = GPT_READY; + gpt_lld_stop_timer(gptp); +} + +/** + * @brief Starts the timer in one shot mode and waits for completion. + * @details This function specifically polls the timer waiting for completion + * in order to not have extra delays caused by interrupt servicing, + * this function is only recommended for short delays. + * @note The configured callback is not invoked when using this function. + * + * @param[in] gptp pointer to the @p GPTDriver object + * @param[in] interval time interval in ticks + * + * @api + */ +void gptPolledDelay(GPTDriver *gptp, gptcnt_t interval) { + + osalDbgAssert(gptp->state == GPT_READY, + "invalid state"); + + gptp->state = GPT_ONESHOT; + gpt_lld_polled_delay(gptp, interval); + gptp->state = GPT_READY; +} + +#endif /* HAL_USE_GPT */ + +/** @} */ -- cgit v1.2.3 From a840a0d418a1ca695412b934637b81f7e38cfef8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 12 Aug 2013 16:13:20 +0000 Subject: Ported EXT. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6142 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/ext.c | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 os/hal/src/ext.c (limited to 'os/hal/src') diff --git a/os/hal/src/ext.c b/os/hal/src/ext.c new file mode 100644 index 000000000..81c92525a --- /dev/null +++ b/os/hal/src/ext.c @@ -0,0 +1,204 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ext.c + * @brief EXT Driver code. + * + * @addtogroup EXT + * @{ + */ + +#include "hal.h" + +#if HAL_USE_EXT || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* 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) { + + osalDbgCheck((extp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), + "invalid state"); + extp->config = config; + ext_lld_start(extp); + extp->state = EXT_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the EXT peripheral. + * + * @param[in] extp pointer to the @p EXTDriver object + * + * @api + */ +void extStop(EXTDriver *extp) { + + osalDbgCheck(extp != NULL); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_STOP) || (extp->state == EXT_ACTIVE), + "invalid state"); + ext_lld_stop(extp); + extp->state = EXT_STOP; + osalSysUnlock(); +} + +/** + * @brief Enables an EXT channel. + * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be enabled + * + * @api + */ +void extChannelEnable(EXTDriver *extp, expchannel_t channel) { + + osalDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_ACTIVE) && + ((extp->config->channels[channel].mode & + EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), + "invalid state"); + extChannelEnableI(extp, channel); + osalSysUnlock(); +} + +/** + * @brief Disables an EXT channel. + * @pre The channel must not be in @p EXT_CH_MODE_DISABLED mode. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be disabled + * + * @api + */ +void extChannelDisable(EXTDriver *extp, expchannel_t channel) { + + osalDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS)); + + osalSysLock(); + osalDbgAssert((extp->state == EXT_ACTIVE) && + ((extp->config->channels[channel].mode & + EXT_CH_MODE_EDGES_MASK) != EXT_CH_MODE_DISABLED), + "invalid state"); + extChannelDisableI(extp, channel); + osalSysUnlock(); +} + +/** + * @brief Changes the operation mode of a channel. + * @note This function attempts to write over the current configuration + * structure that must have been not declared constant. This + * violates the @p const qualifier in @p extStart() but it is + * intentional. + * @note This function cannot be used if the configuration structure is + * declared @p const. + * @note The effect of this function on constant configuration structures + * is not defined. + * + * @param[in] extp pointer to the @p EXTDriver object + * @param[in] channel channel to be changed + * @param[in] extcp new configuration for the channel + * + * @iclass + */ +void extSetChannelModeI(EXTDriver *extp, + expchannel_t channel, + const EXTChannelConfig *extcp) { + EXTChannelConfig *oldcp; + + osalDbgCheck((extp != NULL) && + (channel < EXT_MAX_CHANNELS) && + (extcp != NULL)); + + osalDbgAssert(extp->state == EXT_ACTIVE, "invalid state"); + + /* Note that here the access is enforced as non-const, known access + violation.*/ + oldcp = (EXTChannelConfig *)&extp->config->channels[channel]; + + /* Overwiting the old channels configuration then the channel is reconfigured + by the low level driver.*/ + *oldcp = *extcp; + ext_lld_channel_enable(extp, channel); +} + +#endif /* HAL_USE_EXT */ + +/** @} */ -- cgit v1.2.3 From 60c6d531d4b6b5c5d3d78c4337d267d3fe315c7c Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 12 Aug 2013 16:44:22 +0000 Subject: Ported MMC_SPI. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6145 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_mmcsd.c | 113 +++++++ os/hal/src/mmc_spi.c | 875 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 988 insertions(+) create mode 100644 os/hal/src/hal_mmcsd.c create mode 100644 os/hal/src/mmc_spi.c (limited to 'os/hal/src') diff --git a/os/hal/src/hal_mmcsd.c b/os/hal/src/hal_mmcsd.c new file mode 100644 index 000000000..b2cfb65a0 --- /dev/null +++ b/os/hal/src/hal_mmcsd.c @@ -0,0 +1,113 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file hal_mmcsd.c + * @brief MMC/SD cards common code. + * + * @addtogroup MMCSD + * @{ + */ + +#include "hal.h" + +#if HAL_USE_MMC_SPI || HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Gets a bit field from a words array. + * @note The bit zero is the LSb of the first word. + * + * @param[in] data pointer to the words array + * @param[in] end bit offset of the last bit of the field, inclusive + * @param[in] start bit offset of the first bit of the field, inclusive + * + * @return The bits field value, left aligned. + * + * @notapi + */ +static uint32_t mmcsd_get_slice(uint32_t *data, uint32_t end, uint32_t start) { + unsigned startidx, endidx, startoff; + uint32_t endmask; + + osalDbgCheck((end >= start) && ((end - start) < 32)); + + startidx = start / 32; + startoff = start % 32; + endidx = end / 32; + endmask = (1 << ((end % 32) + 1)) - 1; + + /* One or two pieces?*/ + if (startidx < endidx) + return (data[startidx] >> startoff) | /* Two pieces case. */ + ((data[endidx] & endmask) << (32 - startoff)); + return (data[startidx] & endmask) >> startoff; /* One piece case. */ +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Extract card capacity from a CSD. + * @details The capacity is returned as number of available blocks. + * + * @param[in] csd the CSD record + * + * @return The card capacity. + * @retval 0 CSD format error + */ +uint32_t mmcsdGetCapacity(uint32_t csd[4]) { + + switch (csd[3] >> 30) { + uint32_t a, b, c; + case 0: + /* CSD version 1.0 */ + a = mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_SLICE); + b = mmcsd_get_slice(csd, MMCSD_CSD_10_C_SIZE_MULT_SLICE); + c = mmcsd_get_slice(csd, MMCSD_CSD_10_READ_BL_LEN_SLICE); + return (a + 1) << (b + 2) << (c - 9); /* 2^9 == MMCSD_BLOCK_SIZE. */ + case 1: + /* CSD version 2.0.*/ + return 1024 * (mmcsd_get_slice(csd, MMCSD_CSD_20_C_SIZE_SLICE) + 1); + default: + /* Reserved value detected.*/ + return 0; + } +} + +#endif /* HAL_USE_MMC_SPI || HAL_USE_SDC */ + +/** @} */ diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c new file mode 100644 index 000000000..682ed273b --- /dev/null +++ b/os/hal/src/mmc_spi.c @@ -0,0 +1,875 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/* + Parts of this file have been contributed by Matthias Blaicher. + */ + +/** + * @file mmc_spi.c + * @brief MMC over SPI driver code. + * + * @addtogroup MMC_SPI + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* Forward declarations required by mmc_vmt.*/ +static bool mmc_read(void *instance, uint32_t startblk, + uint8_t *buffer, uint32_t n); +static bool mmc_write(void *instance, uint32_t startblk, + const uint8_t *buffer, uint32_t n); + +/** + * @brief Virtual methods table. + */ +static const struct MMCDriverVMT mmc_vmt = { + (bool (*)(void *))mmc_lld_is_card_inserted, + (bool (*)(void *))mmc_lld_is_write_protected, + (bool (*)(void *))mmcConnect, + (bool (*)(void *))mmcDisconnect, + mmc_read, + mmc_write, + (bool (*)(void *))mmcSync, + (bool (*)(void *, BlockDeviceInfo *))mmcGetInfo +}; + +/** + * @brief Lookup table for CRC-7 ( based on polynomial x^7 + x^3 + 1). + */ +static const uint8_t crc7_lookup_table[256] = { + 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, + 0x6c, 0x65, 0x7e, 0x77, 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26, + 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e, 0x32, 0x3b, 0x20, 0x29, + 0x16, 0x1f, 0x04, 0x0d, 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45, + 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14, 0x63, 0x6a, 0x71, 0x78, + 0x47, 0x4e, 0x55, 0x5c, 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b, + 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13, 0x7d, 0x74, 0x6f, 0x66, + 0x59, 0x50, 0x4b, 0x42, 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a, + 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69, 0x1e, 0x17, 0x0c, 0x05, + 0x3a, 0x33, 0x28, 0x21, 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70, + 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38, 0x41, 0x48, 0x53, 0x5a, + 0x65, 0x6c, 0x77, 0x7e, 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36, + 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67, 0x10, 0x19, 0x02, 0x0b, + 0x34, 0x3d, 0x26, 0x2f, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, + 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x6a, 0x63, 0x78, 0x71, + 0x4e, 0x47, 0x5c, 0x55, 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d, + 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a, 0x6d, 0x64, 0x7f, 0x76, + 0x49, 0x40, 0x5b, 0x52, 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03, + 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b, 0x17, 0x1e, 0x05, 0x0c, + 0x33, 0x3a, 0x21, 0x28, 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60, + 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31, 0x46, 0x4f, 0x54, 0x5d, + 0x62, 0x6b, 0x70, 0x79 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static bool mmc_read(void *instance, uint32_t startblk, + uint8_t *buffer, uint32_t n) { + + if (mmcStartSequentialRead((MMCDriver *)instance, startblk)) + return CH_FAILED; + while (n > 0) { + if (mmcSequentialRead((MMCDriver *)instance, buffer)) + return CH_FAILED; + buffer += MMCSD_BLOCK_SIZE; + n--; + } + if (mmcStopSequentialRead((MMCDriver *)instance)) + return CH_FAILED; + return CH_SUCCESS; +} + +static bool mmc_write(void *instance, uint32_t startblk, + const uint8_t *buffer, uint32_t n) { + + if (mmcStartSequentialWrite((MMCDriver *)instance, startblk)) + return CH_FAILED; + while (n > 0) { + if (mmcSequentialWrite((MMCDriver *)instance, buffer)) + return CH_FAILED; + buffer += MMCSD_BLOCK_SIZE; + n--; + } + if (mmcStopSequentialWrite((MMCDriver *)instance)) + return CH_FAILED; + return CH_SUCCESS; +} + +/** + * @brief Calculate the MMC standard CRC-7 based on a lookup table. + * + * @param[in] crc start value for CRC + * @param[in] buffer pointer to data buffer + * @param[in] len length of data + * @return Calculated CRC + */ +static uint8_t crc7(uint8_t crc, const uint8_t *buffer, size_t len) { + + while (len--) + crc = crc7_lookup_table[(crc << 1) ^ (*buffer++)]; + return crc; +} + +/** + * @brief Waits an idle condition. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @notapi + */ +static void wait(MMCDriver *mmcp) { + int i; + uint8_t buf[4]; + + for (i = 0; i < 16; i++) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFF) + return; + } + /* Looks like it is a long wait.*/ + while (TRUE) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFF) + break; +#ifdef MMC_NICE_WAITING + /* Trying to be nice with the other threads.*/ + chThdSleep(1); +#endif + } +} + +/** + * @brief Sends a command header. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * + * @notapi + */ +static void send_hdr(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { + uint8_t buf[6]; + + /* Wait for the bus to become idle if a write operation was in progress.*/ + wait(mmcp); + + buf[0] = 0x40 | cmd; + buf[1] = arg >> 24; + buf[2] = arg >> 16; + buf[3] = arg >> 8; + buf[4] = arg; + /* Calculate CRC for command header, shift to right position, add stop bit.*/ + buf[5] = ((crc7(0, buf, 5) & 0x7F) << 1) | 0x01; + + spiSend(mmcp->config->spip, 6, buf); +} + +/** + * @brief Receives a single byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The response as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t recvr1(MMCDriver *mmcp) { + int i; + uint8_t r1[1]; + + for (i = 0; i < 9; i++) { + spiReceive(mmcp->config->spip, 1, r1); + if (r1[0] != 0xFF) + return r1[0]; + } + return 0xFF; +} + +/** + * @brief Receives a three byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to four bytes wide buffer + * @return First response byte as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t recvr3(MMCDriver *mmcp, uint8_t* buffer) { + uint8_t r1; + + r1 = recvr1(mmcp); + spiReceive(mmcp->config->spip, 4, buffer); + + return r1; +} + +/** + * @brief Sends a command an returns a single byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * @return The response as an @p uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t send_command_R1(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { + uint8_t r1; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, arg); + r1 = recvr1(mmcp); + spiUnselect(mmcp->config->spip); + return r1; +} + +/** + * @brief Sends a command which returns a five bytes response (R3). + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] cmd the command id + * @param[in] arg the command argument + * @param[out] response pointer to four bytes wide uint8_t buffer + * @return The first byte of the response (R1) as an @p + * uint8_t value. + * @retval 0xFF timed out. + * + * @notapi + */ +static uint8_t send_command_R3(MMCDriver *mmcp, uint8_t cmd, uint32_t arg, + uint8_t *response) { + uint8_t r1; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, arg); + r1 = recvr3(mmcp, response); + spiUnselect(mmcp->config->spip); + return r1; +} + +/** + * @brief Reads the CSD. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] csd pointer to the CSD buffer + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @notapi + */ +static bool read_CxD(MMCDriver *mmcp, uint8_t cmd, uint32_t cxd[4]) { + unsigned i; + uint8_t *bp, buf[16]; + + spiSelect(mmcp->config->spip); + send_hdr(mmcp, cmd, 0); + if (recvr1(mmcp) != 0x00) { + spiUnselect(mmcp->config->spip); + return CH_FAILED; + } + + /* Wait for data availability.*/ + for (i = 0; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFE) { + uint32_t *wp; + + spiReceive(mmcp->config->spip, 16, buf); + bp = buf; + for (wp = &cxd[3]; wp >= cxd; wp--) { + *wp = ((uint32_t)bp[0] << 24) | ((uint32_t)bp[1] << 16) | + ((uint32_t)bp[2] << 8) | (uint32_t)bp[3]; + bp += 4; + } + + /* CRC ignored then end of transaction. */ + spiIgnore(mmcp->config->spip, 2); + spiUnselect(mmcp->config->spip); + + return CH_SUCCESS; + } + } + return CH_FAILED; +} + +/** + * @brief Waits that the card reaches an idle state. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @notapi + */ +static void sync(MMCDriver *mmcp) { + uint8_t buf[1]; + + spiSelect(mmcp->config->spip); + while (TRUE) { + spiReceive(mmcp->config->spip, 1, buf); + if (buf[0] == 0xFF) + break; +#ifdef MMC_NICE_WAITING + chThdSleep(1); /* Trying to be nice with the other threads.*/ +#endif + } + spiUnselect(mmcp->config->spip); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MMC over SPI driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void mmcInit(void) { + +} + +/** + * @brief Initializes an instance. + * + * @param[out] mmcp pointer to the @p MMCDriver object + * + * @init + */ +void mmcObjectInit(MMCDriver *mmcp) { + + mmcp->vmt = &mmc_vmt; + mmcp->state = BLK_STOP; + mmcp->config = NULL; + mmcp->block_addresses = FALSE; +} + +/** + * @brief Configures and activates the MMC peripheral. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] config pointer to the @p MMCConfig object. + * + * @api + */ +void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { + + osalDbgCheck((mmcp != NULL) && (config != NULL)); + osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), + "invalid state"); + + mmcp->config = config; + mmcp->state = BLK_ACTIVE; +} + +/** + * @brief Disables the MMC peripheral. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @api + */ +void mmcStop(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert((mmcp->state == BLK_STOP) || (mmcp->state == BLK_ACTIVE), + "invalid state"); + + spiStop(mmcp->config->spip); + mmcp->state = BLK_STOP; +} + +/** + * @brief Performs the initialization procedure on the inserted card. + * @details This function should be invoked when a card is inserted and + * brings the driver in the @p MMC_READY state where it is possible + * to perform read and write operations. + * @note It is possible to invoke this function from the insertion event + * handler. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded and the driver is now + * in the @p MMC_READY state. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcConnect(MMCDriver *mmcp) { + unsigned i; + uint8_t r3[4]; + + osalDbgCheck(mmcp != NULL); + + osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), + "invalid state"); + + /* Connection procedure in progress.*/ + mmcp->state = BLK_CONNECTING; + + /* Slow clock mode and 128 clock pulses.*/ + spiStart(mmcp->config->spip, mmcp->config->lscfg); + spiIgnore(mmcp->config->spip, 16); + + /* SPI mode selection.*/ + i = 0; + while (TRUE) { + if (send_command_R1(mmcp, MMCSD_CMD_GO_IDLE_STATE, 0) == 0x01) + break; + if (++i >= MMC_CMD0_RETRY) + goto failed; + chThdSleepMilliseconds(10); + } + + /* Try to detect if this is a high capacity card and switch to block + addresses if possible. + This method is based on "How to support SDC Ver2 and high capacity cards" + by ElmChan.*/ + if (send_command_R3(mmcp, MMCSD_CMD_SEND_IF_COND, + MMCSD_CMD8_PATTERN, r3) != 0x05) { + + /* Switch to SDHC mode.*/ + i = 0; + while (TRUE) { + if ((send_command_R1(mmcp, MMCSD_CMD_APP_CMD, 0) == 0x01) && + (send_command_R3(mmcp, MMCSD_CMD_APP_OP_COND, + 0x400001aa, r3) == 0x00)) + break; + + if (++i >= MMC_ACMD41_RETRY) + goto failed; + chThdSleepMilliseconds(10); + } + + /* Execute dedicated read on OCR register */ + send_command_R3(mmcp, MMCSD_CMD_READ_OCR, 0, r3); + + /* Check if CCS is set in response. Card operates in block mode if set.*/ + if (r3[0] & 0x40) + mmcp->block_addresses = TRUE; + } + + /* Initialization.*/ + i = 0; + while (TRUE) { + uint8_t b = send_command_R1(mmcp, MMCSD_CMD_INIT, 0); + if (b == 0x00) + break; + if (b != 0x01) + goto failed; + if (++i >= MMC_CMD1_RETRY) + goto failed; + chThdSleepMilliseconds(10); + } + + /* Initialization complete, full speed.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + + /* Setting block size.*/ + if (send_command_R1(mmcp, MMCSD_CMD_SET_BLOCKLEN, + MMCSD_BLOCK_SIZE) != 0x00) + goto failed; + + /* Determine capacity.*/ + if (read_CxD(mmcp, MMCSD_CMD_SEND_CSD, mmcp->csd)) + goto failed; + mmcp->capacity = mmcsdGetCapacity(mmcp->csd); + if (mmcp->capacity == 0) + goto failed; + + if (read_CxD(mmcp, MMCSD_CMD_SEND_CID, mmcp->cid)) + goto failed; + + mmcp->state = BLK_READY; + return CH_SUCCESS; + + /* Connection failed, state reset to BLK_ACTIVE.*/ +failed: + spiStop(mmcp->config->spip); + mmcp->state = BLK_ACTIVE; + return CH_FAILED; +} + +/** + * @brief Brings the driver in a state safe for card removal. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @return The operation status. + * + * @retval CH_SUCCESS the operation succeeded and the driver is now + * in the @p MMC_INSERTED state. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcDisconnect(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + + osalSysLock(); + osalDbgAssert((mmcp->state == BLK_ACTIVE) || (mmcp->state == BLK_READY), + "invalid state"); + if (mmcp->state == BLK_ACTIVE) { + osalSysUnlock(); + return CH_SUCCESS; + } + mmcp->state = BLK_DISCONNECTING; + osalSysUnlock(); + + /* Wait for the pending write operations to complete.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + sync(mmcp); + + spiStop(mmcp->config->spip); + mmcp->state = BLK_ACTIVE; + return CH_SUCCESS; +} + +/** + * @brief Starts a sequential read. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk first block to read + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); + + /* Read operation in progress.*/ + mmcp->state = BLK_READING; + + /* (Re)starting the SPI in case it has been reprogrammed externally, it can + happen if the SPI bus is shared among multiple peripherals.*/ + spiStart(mmcp->config->spip, mmcp->config->hscfg); + spiSelect(mmcp->config->spip); + + if (mmcp->block_addresses) + send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk); + else + send_hdr(mmcp, MMCSD_CMD_READ_MULTIPLE_BLOCK, startblk * MMCSD_BLOCK_SIZE); + + if (recvr1(mmcp) != 0x00) { + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_FAILED; + } + return CH_SUCCESS; +} + +/** + * @brief Reads a block within a sequential read operation. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to the read buffer + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { + int i; + + osalDbgCheck((mmcp != NULL) && (buffer != NULL)); + + if (mmcp->state != BLK_READING) + return CH_FAILED; + + for (i = 0; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->config->spip, 1, buffer); + if (buffer[0] == 0xFE) { + spiReceive(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer); + /* CRC ignored. */ + spiIgnore(mmcp->config->spip, 2); + return CH_SUCCESS; + } + } + /* Timeout.*/ + spiUnselect(mmcp->config->spip); + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_FAILED; +} + +/** + * @brief Stops a sequential read gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcStopSequentialRead(MMCDriver *mmcp) { + static const uint8_t stopcmd[] = {0x40 | MMCSD_CMD_STOP_TRANSMISSION, + 0, 0, 0, 0, 1, 0xFF}; + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_READING) + return CH_FAILED; + + spiSend(mmcp->config->spip, sizeof(stopcmd), stopcmd); +/* result = recvr1(mmcp) != 0x00;*/ + /* Note, ignored r1 response, it can be not zero, unknown issue.*/ + (void) recvr1(mmcp); + + /* Read operation finished.*/ + spiUnselect(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_SUCCESS; +} + +/** + * @brief Starts a sequential write. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk first block to write + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { + + osalDbgCheck(mmcp != NULL); + osalDbgAssert(mmcp->state == BLK_READY, "invalid state"); + + /* Write operation in progress.*/ + mmcp->state = BLK_WRITING; + + spiStart(mmcp->config->spip, mmcp->config->hscfg); + spiSelect(mmcp->config->spip); + if (mmcp->block_addresses) + send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, startblk); + else + send_hdr(mmcp, MMCSD_CMD_WRITE_MULTIPLE_BLOCK, + startblk * MMCSD_BLOCK_SIZE); + + if (recvr1(mmcp) != 0x00) { + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_FAILED; + } + return CH_SUCCESS; +} + +/** + * @brief Writes a block within a sequential write operation. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] buffer pointer to the write buffer + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer) { + static const uint8_t start[] = {0xFF, 0xFC}; + uint8_t b[1]; + + osalDbgCheck((mmcp != NULL) && (buffer != NULL)); + + if (mmcp->state != BLK_WRITING) + return CH_FAILED; + + spiSend(mmcp->config->spip, sizeof(start), start); /* Data prologue. */ + spiSend(mmcp->config->spip, MMCSD_BLOCK_SIZE, buffer);/* Data. */ + spiIgnore(mmcp->config->spip, 2); /* CRC ignored. */ + spiReceive(mmcp->config->spip, 1, b); + if ((b[0] & 0x1F) == 0x05) { + wait(mmcp); + return CH_SUCCESS; + } + + /* Error.*/ + spiUnselect(mmcp->config->spip); + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_FAILED; +} + +/** + * @brief Stops a sequential write gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcStopSequentialWrite(MMCDriver *mmcp) { + static const uint8_t stop[] = {0xFD, 0xFF}; + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_WRITING) + return CH_FAILED; + + spiSend(mmcp->config->spip, sizeof(stop), stop); + spiUnselect(mmcp->config->spip); + + /* Write operation finished.*/ + mmcp->state = BLK_READY; + return CH_SUCCESS; +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcSync(MMCDriver *mmcp) { + + osalDbgCheck(mmcp != NULL); + + if (mmcp->state != BLK_READY) + return CH_FAILED; + + /* Synchronization operation in progress.*/ + mmcp->state = BLK_SYNCING; + + spiStart(mmcp->config->spip, mmcp->config->hscfg); + sync(mmcp); + + /* Synchronization operation finished.*/ + mmcp->state = BLK_READY; + return CH_SUCCESS; +} + +/** + * @brief Returns the media info. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[out] bdip pointer to a @p BlockDeviceInfo structure + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcGetInfo(MMCDriver *mmcp, BlockDeviceInfo *bdip) { + + osalDbgCheck((mmcp != NULL) && (bdip != NULL)); + + if (mmcp->state != BLK_READY) + return CH_FAILED; + + bdip->blk_num = mmcp->capacity; + bdip->blk_size = MMCSD_BLOCK_SIZE; + + return CH_SUCCESS; +} + +/** + * @brief Erases blocks. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] startblk starting block number + * @param[in] endblk ending block number + * + * @return The operation status. + * @retval CH_SUCCESS the operation succeeded. + * @retval CH_FAILED the operation failed. + * + * @api + */ +bool mmcErase(MMCDriver *mmcp, uint32_t startblk, uint32_t endblk) { + + osalDbgCheck((mmcp != NULL)); + + /* Erase operation in progress.*/ + mmcp->state = BLK_WRITING; + + /* Handling command differences between HC and normal cards.*/ + if (!mmcp->block_addresses) { + startblk *= MMCSD_BLOCK_SIZE; + endblk *= MMCSD_BLOCK_SIZE; + } + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_START, startblk)) + goto failed; + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE_RW_BLK_END, endblk)) + goto failed; + + if (send_command_R1(mmcp, MMCSD_CMD_ERASE, 0)) + goto failed; + + mmcp->state = BLK_READY; + return CH_SUCCESS; + + /* Command failed, state reset to BLK_ACTIVE.*/ +failed: + spiStop(mmcp->config->spip); + mmcp->state = BLK_READY; + return CH_FAILED; +} + +#endif /* HAL_USE_MMC_SPI */ + +/** @} */ -- cgit v1.2.3 From 782415628b7da8871b1ab0d6adfcd0ec325cf485 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 12 Aug 2013 16:55:13 +0000 Subject: Ported UART. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6146 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/uart.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 os/hal/src/uart.c (limited to 'os/hal/src') diff --git a/os/hal/src/uart.c b/os/hal/src/uart.c new file mode 100644 index 000000000..a25b594aa --- /dev/null +++ b/os/hal/src/uart.c @@ -0,0 +1,338 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file uart.c + * @brief UART Driver code. + * + * @addtogroup UART + * @{ + */ + +#include "hal.h" + +#if HAL_USE_UART || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief UART Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void uartInit(void) { + + uart_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p UARTDriver structure. + * + * @param[out] uartp pointer to the @p UARTDriver object + * + * @init + */ +void uartObjectInit(UARTDriver *uartp) { + + uartp->state = UART_STOP; + uartp->txstate = UART_TX_IDLE; + uartp->rxstate = UART_RX_IDLE; + uartp->config = NULL; + /* Optional, user-defined initializer.*/ +#if defined(UART_DRIVER_EXT_INIT_HOOK) + UART_DRIVER_EXT_INIT_HOOK(uartp); +#endif +} + +/** + * @brief Configures and activates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] config pointer to the @p UARTConfig object + * + * @api + */ +void uartStart(UARTDriver *uartp, const UARTConfig *config) { + + osalDbgCheck((uartp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), + "invalid state"); + + uartp->config = config; + uart_lld_start(uartp); + uartp->state = UART_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the UART peripheral. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @api + */ +void uartStop(UARTDriver *uartp) { + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY), + "invalid state"); + + uart_lld_stop(uartp); + uartp->state = UART_STOP; + uartp->txstate = UART_TX_IDLE; + uartp->rxstate = UART_RX_IDLE; + osalSysUnlock(); +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) { + + osalDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + uart_lld_start_send(uartp, n, txbuf); + uartp->txstate = UART_TX_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Starts a transmission on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @iclass + */ +void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) { + + osalDbgCheckClassI(); + osalDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL)); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->txstate != UART_TX_ACTIVE, "tx active"); + + uart_lld_start_send(uartp, n, txbuf); + uartp->txstate = UART_TX_ACTIVE; +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. + * + * @api + */ +size_t uartStopSend(UARTDriver *uartp) { + size_t n; + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->txstate == UART_TX_ACTIVE) { + n = uart_lld_stop_send(uartp); + uartp->txstate = UART_TX_IDLE; + } + else + n = 0; + osalSysUnlock(); + return n; +} + +/** + * @brief Stops any ongoing transmission. + * @note Stopping a transmission also suppresses the transmission callbacks. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not transmitted by the + * stopped transmit operation. + * @retval 0 There was no transmit operation in progress. + * + * @iclass + */ +size_t uartStopSendI(UARTDriver *uartp) { + + osalDbgCheckClassI(); + osalDbgCheck(uartp != NULL); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->txstate == UART_TX_ACTIVE) { + size_t n = uart_lld_stop_send(uartp); + uartp->txstate = UART_TX_IDLE; + return n; + } + return 0; +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[in] rxbuf the pointer to the receive buffer + * + * @api + */ +void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) { + + osalDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL)); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); + + uart_lld_start_receive(uartp, n, rxbuf); + uartp->rxstate = UART_RX_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Starts a receive operation on the UART peripheral. + * @note The buffers are organized as uint8_t arrays for data sizes below + * or equal to 8 bits else it is organized as uint16_t arrays. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * @param[in] n number of data frames to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @iclass + */ +void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) { + + osalDbgCheckClassI(); + osalDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL)); + osalDbgAssert(uartp->state == UART_READY, "is active"); + osalDbgAssert(uartp->rxstate != UART_RX_ACTIVE, "rx active"); + + uart_lld_start_receive(uartp, n, rxbuf); + uartp->rxstate = UART_RX_ACTIVE; +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * @retval 0 There was no receive operation in progress. + * + * @api + */ +size_t uartStopReceive(UARTDriver *uartp) { + size_t n; + + osalDbgCheck(uartp != NULL); + + osalSysLock(); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->rxstate == UART_RX_ACTIVE) { + n = uart_lld_stop_receive(uartp); + uartp->rxstate = UART_RX_IDLE; + } + else + n = 0; + osalSysUnlock(); + return n; +} + +/** + * @brief Stops any ongoing receive operation. + * @note Stopping a receive operation also suppresses the receive callbacks. + * @note This function has to be invoked from a lock zone. + * + * @param[in] uartp pointer to the @p UARTDriver object + * + * @return The number of data frames not received by the + * stopped receive operation. + * @retval 0 There was no receive operation in progress. + * + * @iclass + */ +size_t uartStopReceiveI(UARTDriver *uartp) { + + osalDbgCheckClassI(); + osalDbgCheck(uartp != NULL); + osalDbgAssert(uartp->state == UART_READY, "not active"); + + if (uartp->rxstate == UART_RX_ACTIVE) { + size_t n = uart_lld_stop_receive(uartp); + uartp->rxstate = UART_RX_IDLE; + return n; + } + return 0; +} + +#endif /* HAL_USE_UART */ + +/** @} */ -- cgit v1.2.3 From 44fe821ab47ab7ea6e2415119bb6e068c96872ca Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 15 Aug 2013 14:48:41 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6159 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/pal.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/pal.c b/os/hal/src/pal.c index c2eb50a85..efebc1a94 100644 --- a/os/hal/src/pal.c +++ b/os/hal/src/pal.c @@ -59,11 +59,12 @@ * @note The function internally uses the @p palReadGroup() macro. The use * of this function is preferred when you value code size, readability * and error checking over speed. + * @note The function can be called from any context. * * @param[in] bus the I/O bus, pointer to a @p IOBus structure * @return The bus logical states. * - * @api + * @special */ ioportmask_t palReadBus(IOBus *bus) { @@ -81,13 +82,14 @@ ioportmask_t palReadBus(IOBus *bus) { * @note The default implementation is non atomic and not necessarily * optimal. Low level drivers may optimize the function by using * specific hardware or coding. + * @note The function can be called from any context. * * @param[in] bus the I/O bus, pointer to a @p IOBus structure * @param[in] bits the bits to be written on the I/O bus. Values exceeding * the bus width are masked so most significant bits are * lost. * - * @api + * @special */ void palWriteBus(IOBus *bus, ioportmask_t bits) { @@ -105,11 +107,12 @@ void palWriteBus(IOBus *bus, ioportmask_t bits) { * @note The default implementation is non atomic and not necessarily * optimal. Low level drivers may optimize the function by using * specific hardware or coding. + * @note The function can be called from any context. * * @param[in] bus the I/O bus, pointer to a @p IOBus structure * @param[in] mode the mode * - * @api + * @special */ void palSetBusMode(IOBus *bus, iomode_t mode) { -- cgit v1.2.3 From dbd493cff1bb0c9b0bdd3eeb081a56dbaa0235a8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 17 Aug 2013 15:32:41 +0000 Subject: I2C ported but needs to be reviewed to not use virtual timers directly. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6170 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/i2c.c | 283 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 os/hal/src/i2c.c (limited to 'os/hal/src') diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c new file mode 100644 index 000000000..3e037332b --- /dev/null +++ b/os/hal/src/i2c.c @@ -0,0 +1,283 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file i2c.c + * @brief I2C Driver code. + * + * @addtogroup I2C + * @{ + */ +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2C Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2cInit(void) { + + i2c_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2CDriver structure. + * + * @param[out] i2cp pointer to the @p I2CDriver object + * + * @init + */ +void i2cObjectInit(I2CDriver *i2cp) { + + i2cp->state = I2C_STOP; + i2cp->config = NULL; + +#if I2C_USE_MUTUAL_EXCLUSION + osalMutexObjectInit(&i2cp->mutex); +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + +#if defined(I2C_DRIVER_EXT_INIT_HOOK) + I2C_DRIVER_EXT_INIT_HOOK(i2cp); +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] config pointer to the @p I2CConfig object + * + * @api + */ +void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { + + osalDbgCheck((i2cp != NULL) && (config != NULL)); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2cp->config = config; + i2c_lld_start(i2cp); + i2cp->state = I2C_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cStop(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2c_lld_stop(i2cp); + i2cp->state = I2C_STOP; + osalSysUnlock(); +} + +/** + * @brief Returns the errors mask associated to the previous operation. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @return The errors mask. + * + * @api + */ +i2cflags_t i2cGetErrors(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + return i2c_lld_get_errors(i2cp); +} + +/** + * @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] 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[out] 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] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, + i2caddr_t addr, + const uint8_t *txbuf, + size_t txbytes, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout) { + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0) && + (txbytes > 0) && (txbuf != NULL) && + ((rxbytes == 0) || ((rxbytes > 0) && (rxbuf != NULL))) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_TX; + rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, + rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) + i2cp->state = I2C_LOCKED; + else + i2cp->state = I2C_READY; + osalSysUnlock(); + return rdymsg; +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address (7 bits) without R/W bit + * @param[out] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, + i2caddr_t addr, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout){ + + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0) && + (rxbytes > 0) && (rxbuf != NULL) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_RX; + rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) + i2cp->state = I2C_LOCKED; + else + i2cp->state = I2C_READY; + osalSysUnlock(); + return rdymsg; +} + +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the I2C bus. + * @details This function tries to gain ownership to the SPI bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cAcquireBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + osalMutexLock(&i2cp->mutex); +} + +/** + * @brief Releases exclusive access to the I2C bus. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cReleaseBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + osalMutexUnlock(&i2cp->mutex); +} +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + +#endif /* HAL_USE_I2C */ + +/** @} */ -- cgit v1.2.3 From 7d2ebae5ebb3ae7b1e662a7443cc09e27007995a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 19 Aug 2013 12:43:49 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6176 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal_queues.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c index 89dc03911..52b9daf6c 100644 --- a/os/hal/src/hal_queues.c +++ b/os/hal/src/hal_queues.c @@ -23,8 +23,8 @@ * @brief I/O Queues code. * * @addtogroup io_queues - * @details ChibiOS/RT queues are mostly used in serial-like device drivers. - * The device drivers are usually designed to have a lower side + * @details Queues are mostly used in serial-like device drivers. + * Serial device drivers are usually designed to have a lower side * (lower driver, it is usually an interrupt service routine) and an * upper side (upper driver, accessed by the application threads).
* There are several kind of queues:
-- cgit v1.2.3 From 5901a354ef4dbc849a3f6ed9539597c27cdb3810 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 25 Aug 2013 09:37:34 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6224 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 411 +++++++++++++++++++++++++ os/hal/src/usb.c | 776 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1187 insertions(+) create mode 100644 os/hal/src/serial_usb.c create mode 100644 os/hal/src/usb.c (limited to 'os/hal/src') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c new file mode 100644 index 000000000..b8764a51a --- /dev/null +++ b/os/hal/src/serial_usb.c @@ -0,0 +1,411 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file serial_usb.c + * @brief Serial over USB Driver code. + * + * @addtogroup SERIAL_USB + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SERIAL_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/* + * Current Line Coding. + */ +static cdc_linecoding_t linecoding = { + {0x00, 0x96, 0x00, 0x00}, /* 38400. */ + LC_STOP_1, LC_PARITY_NONE, 8 +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/* + * Interface implementation. + */ + +static size_t write(void *ip, const uint8_t *bp, size_t n) { + + return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, + n, TIME_INFINITE); +} + +static size_t read(void *ip, uint8_t *bp, size_t n) { + + return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, + n, TIME_INFINITE); +} + +static msg_t put(void *ip, uint8_t b) { + + return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, TIME_INFINITE); +} + +static msg_t get(void *ip) { + + return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, TIME_INFINITE); +} + +static msg_t putt(void *ip, uint8_t b, systime_t timeout) { + + return oqPutTimeout(&((SerialUSBDriver *)ip)->oqueue, b, timeout); +} + +static msg_t gett(void *ip, systime_t timeout) { + + return iqGetTimeout(&((SerialUSBDriver *)ip)->iqueue, timeout); +} + +static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) { + + return oqWriteTimeout(&((SerialUSBDriver *)ip)->oqueue, bp, n, time); +} + +static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) { + + return iqReadTimeout(&((SerialUSBDriver *)ip)->iqueue, bp, n, time); +} + +static const struct SerialUSBDriverVMT vmt = { + write, read, put, get, + putt, gett, writet, readt +}; + +/** + * @brief Notification of data removed from the input queue. + */ +static void inotify(io_queue_t *qp) { + size_t n, maxsize; + SerialUSBDriver *sdup = qGetLink(qp); + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) + return; + + /* If there is in the queue enough space to hold at least one packet and + a transaction is not yet started then a new transaction is started for + the available space.*/ + maxsize = sdup->config->usbp->epc[sdup->config->bulk_out]->out_maxsize; + if (!usbGetReceiveStatusI(sdup->config->usbp, sdup->config->bulk_out) && + ((n = iqGetEmptyI(&sdup->iqueue)) >= maxsize)) { + osalSysUnlock(); + + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(sdup->config->usbp, + sdup->config->bulk_out, + &sdup->iqueue, n); + + osalSysLock(); + usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out); + } +} + +/** + * @brief Notification of data inserted into the output queue. + */ +static void onotify(io_queue_t *qp) { + size_t n; + SerialUSBDriver *sdup = qGetLink(qp); + + /* If the USB driver is not in the appropriate state then transactions + must not be started.*/ + if ((usbGetDriverStateI(sdup->config->usbp) != USB_ACTIVE) || + (sdup->state != SDU_READY)) + return; + + /* If there is not an ongoing transaction and the output queue contains + data then a new transaction is started.*/ + if (!usbGetTransmitStatusI(sdup->config->usbp, sdup->config->bulk_in) && + ((n = oqGetFullI(&sdup->oqueue)) > 0)) { + osalSysUnlock(); + + usbPrepareQueuedTransmit(sdup->config->usbp, + sdup->config->bulk_in, + &sdup->oqueue, n); + + osalSysLock(); + usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in); + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Serial Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sduInit(void) { +} + +/** + * @brief Initializes a generic full duplex driver object. + * @details The HW dependent part of the initialization has to be performed + * outside, usually in the hardware initialization code. + * + * @param[out] sdup pointer to a @p SerialUSBDriver structure + * + * @init + */ +void sduObjectInit(SerialUSBDriver *sdup) { + + sdup->vmt = &vmt; + osalEventObjectInit(&sdup->event); + sdup->state = SDU_STOP; + iqObjectInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup); + oqObjectInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup); +} + +/** + * @brief Configures and starts the driver. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * @param[in] config the serial over USB driver configuration + * + * @api + */ +void sduStart(SerialUSBDriver *sdup, const SerialUSBConfig *config) { + USBDriver *usbp = config->usbp; + + osalDbgCheck(sdup != NULL); + + osalSysLock(); + osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "invalid state"); + usbp->in_params[config->bulk_in - 1] = sdup; + usbp->out_params[config->bulk_out - 1] = sdup; + usbp->in_params[config->int_in - 1] = sdup; + sdup->config = config; + sdup->state = SDU_READY; + osalSysUnlock(); +} + +/** + * @brief Stops the driver. + * @details Any thread waiting on the driver's queues will be awakened with + * the message @p Q_RESET. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @api + */ +void sduStop(SerialUSBDriver *sdup) { + USBDriver *usbp = sdup->config->usbp; + + osalDbgCheck(sdup != NULL); + + osalSysLock(); + + osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY), + "invalid state"); + + /* Driver in stopped state.*/ + usbp->in_params[sdup->config->bulk_in - 1] = NULL; + usbp->out_params[sdup->config->bulk_out - 1] = NULL; + usbp->in_params[sdup->config->int_in - 1] = NULL; + sdup->state = SDU_STOP; + + /* Queues reset in order to signal the driver stop to the application.*/ + chnAddFlagsI(sdup, CHN_DISCONNECTED); + iqResetI(&sdup->iqueue); + iqResetI(&sdup->oqueue); + osalOsRescheduleS(); + + osalSysUnlock(); +} + +/** + * @brief USB device configured handler. + * + * @param[in] sdup pointer to a @p SerialUSBDriver object + * + * @iclass + */ +void sduConfigureHookI(SerialUSBDriver *sdup) { + USBDriver *usbp = sdup->config->usbp; + + iqResetI(&sdup->iqueue); + oqResetI(&sdup->oqueue); + chnAddFlagsI(sdup, CHN_CONNECTED); + + /* Starts the first OUT transaction immediately.*/ + usbPrepareQueuedReceive(usbp, sdup->config->bulk_out, &sdup->iqueue, + usbp->epc[sdup->config->bulk_out]->out_maxsize); + usbStartReceiveI(usbp, sdup->config->bulk_out); +} + +/** + * @brief Default requests hook. + * @details Applications wanting to use the Serial over USB driver can use + * this function as requests hook in the USB configuration. + * The following requests are emulated: + * - CDC_GET_LINE_CODING. + * - CDC_SET_LINE_CODING. + * - CDC_SET_CONTROL_LINE_STATE. + * . + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The hook status. + * @retval TRUE Message handled internally. + * @retval FALSE Message not handled. + */ +bool_t sduRequestsHook(USBDriver *usbp) { + + if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { + switch (usbp->setup[1]) { + case CDC_GET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return TRUE; + case CDC_SET_LINE_CODING: + usbSetupTransfer(usbp, (uint8_t *)&linecoding, sizeof(linecoding), NULL); + return TRUE; + case CDC_SET_CONTROL_LINE_STATE: + /* Nothing to do, there are no control lines.*/ + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + default: + return FALSE; + } + } + return FALSE; +} + +/** + * @brief Default data transmitted callback. + * @details The application must use this function as callback for the IN + * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + */ +void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { + size_t n; + SerialUSBDriver *sdup = usbp->in_params[ep - 1]; + + if (sdup == NULL) + return; + + osalSysLockFromISR(); + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); + + if ((n = oqGetFullI(&sdup->oqueue)) > 0) { + /* The endpoint cannot be busy, we are in the context of the callback, + so it is safe to transmit without a check.*/ + osalSysUnlockFromISR(); + + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, n); + + osalSysLockFromISR(); + usbStartTransmitI(usbp, ep); + } + else if ((usbp->epc[ep]->in_state->txsize > 0) && + !(usbp->epc[ep]->in_state->txsize & + (usbp->epc[ep]->in_maxsize - 1))) { + /* Transmit zero sized packet in case the last one has maximum allowed + size. Otherwise the recipient may expect more data coming soon and + not return buffered data to app. See section 5.8.3 Bulk Transfer + Packet Size Constraints of the USB Specification document.*/ + osalSysUnlockFromISR(); + + usbPrepareQueuedTransmit(usbp, ep, &sdup->oqueue, 0); + + osalSysLockFromISR(); + usbStartTransmitI(usbp, ep); + } + + osalSysUnlockFromISR(); +} + +/** + * @brief Default data received callback. + * @details The application must use this function as callback for the OUT + * data endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + */ +void sduDataReceived(USBDriver *usbp, usbep_t ep) { + size_t n, maxsize; + SerialUSBDriver *sdup = usbp->out_params[ep - 1]; + + if (sdup == NULL) + return; + + osalSysLockFromISR(); + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); + + /* Writes to the input queue can only happen when there is enough space + to hold at least one packet.*/ + maxsize = usbp->epc[ep]->out_maxsize; + if ((n = iqGetEmptyI(&sdup->iqueue)) >= maxsize) { + /* The endpoint cannot be busy, we are in the context of the callback, + so a packet is in the buffer for sure.*/ + osalSysUnlockFromISR(); + + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(usbp, ep, &sdup->iqueue, n); + + osalSysLockFromISR(); + usbStartReceiveI(usbp, ep); + } + + osalSysUnlockFromISR(); +} + +/** + * @brief Default data received callback. + * @details The application must use this function as callback for the IN + * interrupt endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + */ +void sduInterruptTransmitted(USBDriver *usbp, usbep_t ep) { + + (void)usbp; + (void)ep; +} + +#endif /* HAL_USE_SERIAL */ + +/** @} */ diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c new file mode 100644 index 000000000..906981db2 --- /dev/null +++ b/os/hal/src/usb.c @@ -0,0 +1,776 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file usb.c + * @brief USB Driver code. + * + * @addtogroup USB + * @{ + */ + +#include + +#include "hal.h" + +#if HAL_USE_USB || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +static const uint8_t zero_status[] = {0x00, 0x00}; +static const uint8_t active_status[] ={0x00, 0x00}; +static const uint8_t halted_status[] = {0x01, 0x00}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief SET ADDRESS transaction callback. + * + * @param[in] usbp pointer to the @p USBDriver object + */ +static void set_address(USBDriver *usbp) { + + usbp->address = usbp->setup[2]; + usb_lld_set_address(usbp); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_ADDRESS); + usbp->state = USB_SELECTED; +} + +/** + * @brief Standard requests handler. + * @details This is the standard requests default handler, most standard + * requests are handled here, the user can override the standard + * handling using the @p requests_hook_cb hook in the + * @p USBConfig structure. + * + * @param[in] usbp pointer to the @p USBDriver object + * @return The request handling exit code. + * @retval FALSE Request not recognized by the handler or error. + * @retval TRUE Request handled. + */ +static bool_t default_handler(USBDriver *usbp) { + const USBDescriptor *dp; + + /* Decoding the request.*/ + switch (((usbp->setup[0] & (USB_RTYPE_RECIPIENT_MASK | + USB_RTYPE_TYPE_MASK)) | + (usbp->setup[1] << 8))) { + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_STATUS << 8): + /* Just returns the current status word.*/ + usbSetupTransfer(usbp, (uint8_t *)&usbp->status, 2, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_CLEAR_FEATURE << 8): + /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature + number is handled as an error.*/ + if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { + usbp->status &= ~2; + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + } + return FALSE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_FEATURE << 8): + /* Only the DEVICE_REMOTE_WAKEUP is handled here, any other feature + number is handled as an error.*/ + if (usbp->setup[2] == USB_FEATURE_DEVICE_REMOTE_WAKEUP) { + usbp->status |= 2; + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + } + return FALSE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_ADDRESS << 8): + /* The SET_ADDRESS handling can be performed here or postponed after + the status packed depending on the USB_SET_ADDRESS_MODE low + driver setting.*/ +#if USB_SET_ADDRESS_MODE == USB_EARLY_SET_ADDRESS + if ((usbp->setup[0] == USB_RTYPE_RECIPIENT_DEVICE) && + (usbp->setup[1] == USB_REQ_SET_ADDRESS)) + set_address(usbp); + usbSetupTransfer(usbp, NULL, 0, NULL); +#else + usbSetupTransfer(usbp, NULL, 0, set_address); +#endif + return TRUE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_DESCRIPTOR << 8): + /* Handling descriptor requests from the host.*/ + dp = usbp->config->get_descriptor_cb( + usbp, usbp->setup[3], usbp->setup[2], + usbFetchWord(&usbp->setup[4])); + if (dp == NULL) + return FALSE; + usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_GET_CONFIGURATION << 8): + /* Returning the last selected configuration.*/ + usbSetupTransfer(usbp, &usbp->configuration, 1, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_CONFIGURATION << 8): + /* Handling configuration selection from the host.*/ + usbp->configuration = usbp->setup[2]; + if (usbp->configuration == 0) + usbp->state = USB_SELECTED; + else + usbp->state = USB_ACTIVE; + _usb_isr_invoke_event_cb(usbp, USB_EVENT_CONFIGURED); + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_STATUS << 8): + case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SYNCH_FRAME << 8): + /* Just sending two zero bytes, the application can change the behavior + using a hook..*/ + usbSetupTransfer(usbp, (uint8_t *)zero_status, 2, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_GET_STATUS << 8): + /* Sending the EP status.*/ + if (usbp->setup[4] & 0x80) { + switch (usb_lld_get_status_in(usbp, usbp->setup[4] & 0x0F)) { + case EP_STATUS_STALLED: + usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); + return TRUE; + case EP_STATUS_ACTIVE: + usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); + return TRUE; + default: + return FALSE; + } + } + else { + switch (usb_lld_get_status_out(usbp, usbp->setup[4] & 0x0F)) { + case EP_STATUS_STALLED: + usbSetupTransfer(usbp, (uint8_t *)halted_status, 2, NULL); + return TRUE; + case EP_STATUS_ACTIVE: + usbSetupTransfer(usbp, (uint8_t *)active_status, 2, NULL); + return TRUE; + default: + return FALSE; + } + } + case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_CLEAR_FEATURE << 8): + /* Only ENDPOINT_HALT is handled as feature.*/ + if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) + return FALSE; + /* Clearing the EP status, not valid for EP0, it is ignored in that case.*/ + if ((usbp->setup[4] & 0x0F) > 0) { + if (usbp->setup[4] & 0x80) + usb_lld_clear_in(usbp, usbp->setup[4] & 0x0F); + else + usb_lld_clear_out(usbp, usbp->setup[4] & 0x0F); + } + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_ENDPOINT | (USB_REQ_SET_FEATURE << 8): + /* Only ENDPOINT_HALT is handled as feature.*/ + if (usbp->setup[2] != USB_FEATURE_ENDPOINT_HALT) + return FALSE; + /* Stalling the EP, not valid for EP0, it is ignored in that case.*/ + if ((usbp->setup[4] & 0x0F) > 0) { + if (usbp->setup[4] & 0x80) + usb_lld_stall_in(usbp, usbp->setup[4] & 0x0F); + else + usb_lld_stall_out(usbp, usbp->setup[4] & 0x0F); + } + usbSetupTransfer(usbp, NULL, 0, NULL); + return TRUE; + case USB_RTYPE_RECIPIENT_DEVICE | (USB_REQ_SET_DESCRIPTOR << 8): + case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_CLEAR_FEATURE << 8): + case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_FEATURE << 8): + case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_GET_INTERFACE << 8): + case USB_RTYPE_RECIPIENT_INTERFACE | (USB_REQ_SET_INTERFACE << 8): + /* All the above requests are not handled here, if you need them then + use the hook mechanism and provide handling.*/ + default: + return FALSE; + } +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief USB Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void usbInit(void) { + + usb_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p USBDriver structure. + * + * @param[out] usbp pointer to the @p USBDriver object + * + * @init + */ +void usbObjectInit(USBDriver *usbp) { + unsigned i; + + usbp->state = USB_STOP; + usbp->config = NULL; + for (i = 0; i < USB_MAX_ENDPOINTS; i++) { + usbp->in_params[i] = NULL; + usbp->out_params[i] = NULL; + } + usbp->transmitting = 0; + usbp->receiving = 0; +} + +/** + * @brief Configures and activates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] config pointer to the @p USBConfig object + * + * @api + */ +void usbStart(USBDriver *usbp, const USBConfig *config) { + unsigned i; + + osalDbgCheck((usbp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY), + "invalid state"); + usbp->config = config; + for (i = 0; i <= USB_MAX_ENDPOINTS; i++) + usbp->epc[i] = NULL; + usb_lld_start(usbp); + usbp->state = USB_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the USB peripheral. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @api + */ +void usbStop(USBDriver *usbp) { + + osalDbgCheck(usbp != NULL); + + osalSysLock(); + osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) || + (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE), + "invalid state"); + usb_lld_stop(usbp); + usbp->state = USB_STOP; + osalSysUnlock(); +} + +/** + * @brief Enables an endpoint. + * @details This function enables an endpoint, both IN and/or OUT directions + * depending on the configuration structure. + * @note This function must be invoked in response of a SET_CONFIGURATION + * or SET_INTERFACE message. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] epcp the endpoint configuration + * + * @iclass + */ +void usbInitEndpointI(USBDriver *usbp, usbep_t ep, + const USBEndpointConfig *epcp) { + + osalDbgCheckClassI(); + osalDbgCheck((usbp != NULL) && (epcp != NULL)); + osalDbgAssert(usbp->state == USB_ACTIVE, + "invalid state"); + osalDbgAssert(usbp->epc[ep] == NULL, "already initialized"); + + /* Logically enabling the endpoint in the USBDriver structure.*/ + if (epcp->in_state != NULL) + memset(epcp->in_state, 0, sizeof(USBInEndpointState)); + if (epcp->out_state != NULL) + memset(epcp->out_state, 0, sizeof(USBOutEndpointState)); + + usbp->epc[ep] = epcp; + + /* Low level endpoint activation.*/ + usb_lld_init_endpoint(usbp, ep); +} + +/** + * @brief Disables all the active endpoints. + * @details This function disables all the active endpoints except the + * endpoint zero. + * @note This function must be invoked in response of a SET_CONFIGURATION + * message with configuration number zero. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @iclass + */ +void usbDisableEndpointsI(USBDriver *usbp) { + unsigned i; + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + osalDbgAssert(usbp->state == USB_SELECTED, "invalid state"); + + usbp->transmitting &= ~1; + usbp->receiving &= ~1; + for (i = 1; i <= USB_MAX_ENDPOINTS; i++) + usbp->epc[i] = NULL; + + /* Low level endpoints deactivation.*/ + usb_lld_disable_endpoints(usbp); +} + +/** + * @brief Prepares for a receive transaction on an OUT endpoint. + * @post The endpoint is ready for @p usbStartReceiveI(). + * @note This function can be called both in ISR and thread context. + * + * @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 transaction size + * + * @special + */ +void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) { + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + osp->rxqueued = FALSE; + osp->mode.linear.rxbuf = buf; + osp->rxsize = n; + osp->rxcnt = 0; + + usb_lld_prepare_receive(usbp, ep); +} + +/** + * @brief Prepares for a transmit transaction on an IN endpoint. + * @post The endpoint is ready for @p usbStartTransmitI(). + * @note This function can be called both in ISR and thread context. + * @note The queue must contain at least the amount of data specified + * as transaction size. + * + * @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 transaction size + * + * @special + */ +void usbPrepareTransmit(USBDriver *usbp, usbep_t ep, + const uint8_t *buf, size_t n) { + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + isp->txqueued = FALSE; + isp->mode.linear.txbuf = buf; + isp->txsize = n; + isp->txcnt = 0; + + usb_lld_prepare_transmit(usbp, ep); +} + +/** + * @brief Prepares for a receive transaction on an OUT endpoint. + * @post The endpoint is ready for @p usbStartReceiveI(). + * @note This function can be called both in ISR and thread context. + * @note The queue must have enough free space to accommodate the + * specified transaction size rounded to the next packet size + * boundary. For example if the transaction size is 1 and the + * packet size is 64 then the queue must have space for at least + * 64 bytes. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] iqp input queue to be filled with incoming data + * @param[in] n transaction size + * + * @special + */ +void usbPrepareQueuedReceive(USBDriver *usbp, usbep_t ep, + input_queue_t *iqp, size_t n) { + USBOutEndpointState *osp = usbp->epc[ep]->out_state; + + osp->rxqueued = TRUE; + osp->mode.queue.rxqueue = iqp; + osp->rxsize = n; + osp->rxcnt = 0; + + usb_lld_prepare_receive(usbp, ep); +} + +/** + * @brief Prepares for a transmit transaction on an IN endpoint. + * @post The endpoint is ready for @p usbStartTransmitI(). + * @note This function can be called both in ISR and thread context. + * @note The transmit transaction size is equal to the data contained + * in the queue. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * @param[in] oqp output queue to be fetched for outgoing data + * @param[in] n transaction size + * + * @special + */ +void usbPrepareQueuedTransmit(USBDriver *usbp, usbep_t ep, + output_queue_t *oqp, size_t n) { + USBInEndpointState *isp = usbp->epc[ep]->in_state; + + isp->txqueued = TRUE; + isp->mode.queue.txqueue = oqp; + isp->txsize = n; + isp->txcnt = 0; + + usb_lld_prepare_transmit(usbp, ep); +} + +/** + * @brief Starts a receive transaction on an OUT endpoint. + * @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 + * + * @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) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetReceiveStatusI(usbp, ep)) + return TRUE; + + usbp->receiving |= (1 << ep); + usb_lld_start_out(usbp, ep); + return FALSE; +} + +/** + * @brief Starts a transmit transaction on an IN endpoint. + * @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 + * + * @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) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetTransmitStatusI(usbp, ep)) + return TRUE; + + usbp->transmitting |= (1 << ep); + usb_lld_start_in(usbp, ep); + return FALSE; +} + +/** + * @brief Stalls an OUT endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @return The operation status. + * @retval FALSE Endpoint stalled. + * @retval TRUE Endpoint busy, not stalled. + * + * @iclass + */ +bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetReceiveStatusI(usbp, ep)) + return TRUE; + + usb_lld_stall_out(usbp, ep); + return FALSE; +} + +/** + * @brief Stalls an IN endpoint. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number + * + * @return The operation status. + * @retval FALSE Endpoint stalled. + * @retval TRUE Endpoint busy, not stalled. + * + * @iclass + */ +bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep) { + + osalDbgCheckClassI(); + osalDbgCheck(usbp != NULL); + + if (usbGetTransmitStatusI(usbp, ep)) + return TRUE; + + usb_lld_stall_in(usbp, ep); + return FALSE; +} + +/** + * @brief USB reset routine. + * @details This function must be invoked when an USB bus reset condition is + * detected. + * + * @param[in] usbp pointer to the @p USBDriver object + * + * @notapi + */ +void _usb_reset(USBDriver *usbp) { + unsigned i; + + usbp->state = USB_READY; + usbp->status = 0; + usbp->address = 0; + usbp->configuration = 0; + usbp->transmitting = 0; + usbp->receiving = 0; + + /* Invalidates all endpoints into the USBDriver structure.*/ + for (i = 0; i <= USB_MAX_ENDPOINTS; i++) + usbp->epc[i] = NULL; + + /* EP0 state machine initialization.*/ + usbp->ep0state = USB_EP0_WAITING_SETUP; + + /* Low level reset.*/ + usb_lld_reset(usbp); +} + +/** + * @brief Default EP0 SETUP callback. + * @details This function is used by the low level driver as default handler + * for EP0 SETUP events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { + size_t max; + + usbp->ep0state = USB_EP0_WAITING_SETUP; + usbReadSetup(usbp, ep, usbp->setup); + + /* First verify if the application has an handler installed for this + request.*/ + if (!(usbp->config->requests_hook_cb) || + !(usbp->config->requests_hook_cb(usbp))) { + /* Invoking the default handler, if this fails then stalls the + endpoint zero as error.*/ + if (((usbp->setup[0] & USB_RTYPE_TYPE_MASK) != USB_RTYPE_TYPE_STD) || + !default_handler(usbp)) { + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; + return; + } + } + + /* Transfer preparation. The request handler must have populated + correctly the fields ep0next, ep0n and ep0endcb using the macro + usbSetupTransfer().*/ + max = usbFetchWord(&usbp->setup[6]); + /* The transfer size cannot exceed the specified amount.*/ + if (usbp->ep0n > max) + usbp->ep0n = max; + if ((usbp->setup[0] & USB_RTYPE_DIR_MASK) == USB_RTYPE_DIR_DEV2HOST) { + /* IN phase.*/ + if (usbp->ep0n > 0) { + /* Starts the transmit phase.*/ + usbp->ep0state = USB_EP0_TX; + usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n); + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0); + osalSysUnlockFromISR(); + } + else { + /* No transmission phase, directly receiving the zero sized status + packet.*/ + usbp->ep0state = USB_EP0_WAITING_STS; + usbPrepareReceive(usbp, 0, NULL, 0); + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0); + osalSysUnlockFromISR(); + } + } + else { + /* OUT phase.*/ + if (usbp->ep0n > 0) { + /* Starts the receive phase.*/ + usbp->ep0state = USB_EP0_RX; + usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n); + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0); + osalSysUnlockFromISR(); + } + else { + /* No receive phase, directly sending the zero sized status + packet.*/ + usbp->ep0state = USB_EP0_SENDING_STS; + usbPrepareTransmit(usbp, 0, NULL, 0); + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0); + osalSysUnlockFromISR(); + } + } +} + +/** + * @brief Default EP0 IN callback. + * @details This function is used by the low level driver as default handler + * for EP0 IN events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0in(USBDriver *usbp, usbep_t ep) { + size_t max; + + (void)ep; + switch (usbp->ep0state) { + case USB_EP0_TX: + max = usbFetchWord(&usbp->setup[6]); + /* If the transmitted size is less than the requested size and it is a + multiple of the maximum packet size then a zero size packet must be + transmitted.*/ + if ((usbp->ep0n < max) && ((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0)) { + usbPrepareTransmit(usbp, 0, NULL, 0); + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0); + osalSysUnlockFromISR(); + usbp->ep0state = USB_EP0_WAITING_TX0; + return; + } + /* Falls into, it is intentional.*/ + case USB_EP0_WAITING_TX0: + /* Transmit phase over, receiving the zero sized status packet.*/ + usbp->ep0state = USB_EP0_WAITING_STS; + usbPrepareReceive(usbp, 0, NULL, 0); + osalSysLockFromISR(); + usbStartReceiveI(usbp, 0); + osalSysUnlockFromISR(); + return; + case USB_EP0_SENDING_STS: + /* Status packet sent, invoking the callback if defined.*/ + if (usbp->ep0endcb != NULL) + usbp->ep0endcb(usbp); + usbp->ep0state = USB_EP0_WAITING_SETUP; + return; + default: + ; + } + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; +} + +/** + * @brief Default EP0 OUT callback. + * @details This function is used by the low level driver as default handler + * for EP0 OUT events. + * + * @param[in] usbp pointer to the @p USBDriver object + * @param[in] ep endpoint number, always zero + * + * @notapi + */ +void _usb_ep0out(USBDriver *usbp, usbep_t ep) { + + (void)ep; + switch (usbp->ep0state) { + case USB_EP0_RX: + /* Receive phase over, sending the zero sized status packet.*/ + usbp->ep0state = USB_EP0_SENDING_STS; + usbPrepareTransmit(usbp, 0, NULL, 0); + osalSysLockFromISR(); + usbStartTransmitI(usbp, 0); + osalSysUnlockFromISR(); + return; + case USB_EP0_WAITING_STS: + /* Status packet received, it must be zero sized, invoking the callback + if defined.*/ + if (usbGetReceiveTransactionSizeI(usbp, 0) != 0) + break; + if (usbp->ep0endcb != NULL) + usbp->ep0endcb(usbp); + usbp->ep0state = USB_EP0_WAITING_SETUP; + return; + default: + ; + } + /* Error response, the state machine goes into an error state, the low + level layer will have to reset it to USB_EP0_WAITING_SETUP after + receiving a SETUP packet.*/ + usb_lld_stall_in(usbp, 0); + usb_lld_stall_out(usbp, 0); + _usb_isr_invoke_event_cb(usbp, USB_EVENT_STALLED); + usbp->ep0state = USB_EP0_ERROR; +} + +#endif /* HAL_USE_USB */ + +/** @} */ -- cgit v1.2.3 From 867c7c95aa67ea1f19286c3593500214101bacd9 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 5 Sep 2013 09:01:21 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6262 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 2 +- os/hal/src/usb.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index b8764a51a..7a9476250 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -289,7 +289,7 @@ void sduConfigureHookI(SerialUSBDriver *sdup) { * @retval TRUE Message handled internally. * @retval FALSE Message not handled. */ -bool_t sduRequestsHook(USBDriver *usbp) { +bool sduRequestsHook(USBDriver *usbp) { if ((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) { switch (usbp->setup[1]) { diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index 906981db2..a84702b5b 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -77,7 +77,7 @@ static void set_address(USBDriver *usbp) { * @retval FALSE Request not recognized by the handler or error. * @retval TRUE Request handled. */ -static bool_t default_handler(USBDriver *usbp) { +static bool default_handler(USBDriver *usbp) { const USBDescriptor *dp; /* Decoding the request.*/ @@ -471,7 +471,7 @@ void usbPrepareQueuedTransmit(USBDriver *usbp, usbep_t ep, * * @iclass */ -bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) { +bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); @@ -498,7 +498,7 @@ bool_t usbStartReceiveI(USBDriver *usbp, usbep_t ep) { * * @iclass */ -bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) { +bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); @@ -523,7 +523,7 @@ bool_t usbStartTransmitI(USBDriver *usbp, usbep_t ep) { * * @iclass */ -bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) { +bool usbStallReceiveI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); @@ -547,7 +547,7 @@ bool_t usbStallReceiveI(USBDriver *usbp, usbep_t ep) { * * @iclass */ -bool_t usbStallTransmitI(USBDriver *usbp, usbep_t ep) { +bool usbStallTransmitI(USBDriver *usbp, usbep_t ep) { osalDbgCheckClassI(); osalDbgCheck(usbp != NULL); -- cgit v1.2.3 From 1e7ce9301626ece84c0811c3a4cd55fa60b8680d Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 Sep 2013 10:49:21 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6306 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/sdc.c | 572 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 572 insertions(+) create mode 100644 os/hal/src/sdc.c (limited to 'os/hal/src') diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c new file mode 100644 index 000000000..48d181549 --- /dev/null +++ b/os/hal/src/sdc.c @@ -0,0 +1,572 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file sdc.c + * @brief SDC Driver code. + * + * @addtogroup SDC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_SDC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Virtual methods table. + */ +static const struct SDCDriverVMT sdc_vmt = { + (bool (*)(void *))sdc_lld_is_card_inserted, + (bool (*)(void *))sdc_lld_is_write_protected, + (bool (*)(void *))sdcConnect, + (bool (*)(void *))sdcDisconnect, + (bool (*)(void *, uint32_t, uint8_t *, uint32_t))sdcRead, + (bool (*)(void *, uint32_t, const uint8_t *, uint32_t))sdcWrite, + (bool (*)(void *))sdcSync, + (bool (*)(void *, BlockDeviceInfo *))sdcGetInfo +}; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Wait for the card to complete pending operations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @notapi + */ +bool _sdc_wait_for_transfer_state(SDCDriver *sdcp) { + uint32_t resp[1]; + + while (TRUE) { + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_STATUS, + sdcp->rca, resp) || + MMCSD_R1_ERROR(resp[0])) + return HAL_FAILED; + switch (MMCSD_R1_STS(resp[0])) { + case MMCSD_STS_TRAN: + return HAL_SUCCESS; + case MMCSD_STS_DATA: + case MMCSD_STS_RCV: + case MMCSD_STS_PRG: +#if SDC_NICE_WAITING + osalThreadSleepMilliseconds(1); +#endif + continue; + default: + /* The card should have been initialized so any other state is not + valid and is reported as an error.*/ + return HAL_FAILED; + } + } + /* If something going too wrong.*/ + return HAL_FAILED; +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief SDC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void sdcInit(void) { + + sdc_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SDCDriver structure. + * + * @param[out] sdcp pointer to the @p SDCDriver object + * + * @init + */ +void sdcObjectInit(SDCDriver *sdcp) { + + sdcp->vmt = &sdc_vmt; + sdcp->state = BLK_STOP; + sdcp->errors = SDC_NO_ERROR; + sdcp->config = NULL; + sdcp->capacity = 0; +} + +/** + * @brief Configures and activates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] config pointer to the @p SDCConfig object, can be @p NULL if + * the driver supports a default configuration or + * requires no configuration + * + * @api + */ +void sdcStart(SDCDriver *sdcp, const SDCConfig *config) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), + "invalid state"); + sdcp->config = config; + sdc_lld_start(sdcp); + sdcp->state = BLK_ACTIVE; + osalSysUnlock(); +} + +/** + * @brief Deactivates the SDC peripheral. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @api + */ +void sdcStop(SDCDriver *sdcp) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_STOP) || (sdcp->state == BLK_ACTIVE), + "invalid state"); + sdc_lld_stop(sdcp); + sdcp->state = BLK_STOP; + osalSysUnlock(); +} + +/** + * @brief Performs the initialization procedure on the inserted card. + * @details This function should be invoked when a card is inserted and + * brings the driver in the @p BLK_READY state where it is possible + * to perform read and write operations. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcConnect(SDCDriver *sdcp) { + uint32_t resp[1]; + + osalDbgCheck(sdcp != NULL); + osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), + "invalid state"); + + /* Connection procedure in progress.*/ + sdcp->state = BLK_CONNECTING; + + /* Card clock initialization.*/ + sdc_lld_start_clk(sdcp); + + /* Enforces the initial card state.*/ + sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); + + /* V2.0 cards detection.*/ + if (!sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_IF_COND, + MMCSD_CMD8_PATTERN, resp)) { + sdcp->cardmode = SDC_MODE_CARDTYPE_SDV20; + /* Voltage verification.*/ + if (((resp[0] >> 8) & 0xF) != 1) + goto failed; + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + } + else { +#if SDC_MMC_SUPPORT + /* MMC or SD V1.1 detection.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) + sdcp->cardmode = SDC_MODE_CARDTYPE_MMC; + else +#endif /* SDC_MMC_SUPPORT */ + sdcp->cardmode = SDC_MODE_CARDTYPE_SDV11; + } + +#if SDC_MMC_SUPPORT + if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_MMC) { + /* TODO: MMC initialization.*/ + goto failed; + } + else +#endif /* SDC_MMC_SUPPORT */ + { + unsigned i; + uint32_t ocr; + + /* SD initialization.*/ + if ((sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) == SDC_MODE_CARDTYPE_SDV20) + ocr = 0xC0100000; + else + ocr = 0x80100000; + + /* SD-type initialization. */ + i = 0; + while (TRUE) { + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, 0, resp) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + if (sdc_lld_send_cmd_short(sdcp, MMCSD_CMD_APP_OP_COND, ocr, resp)) + goto failed; + if ((resp[0] & 0x80000000) != 0) { + if (resp[0] & 0x40000000) + sdcp->cardmode |= SDC_MODE_HIGH_CAPACITY; + break; + } + if (++i >= SDC_INIT_RETRY) + goto failed; + osalThreadSleepMilliseconds(10); + } + } + + /* Reads CID.*/ + if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_ALL_SEND_CID, 0, sdcp->cid)) + goto failed; + + /* Asks for the RCA.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEND_RELATIVE_ADDR, + 0, &sdcp->rca)) + goto failed; + + /* Reads CSD.*/ + if (sdc_lld_send_cmd_long_crc(sdcp, MMCSD_CMD_SEND_CSD, + sdcp->rca, sdcp->csd)) + goto failed; + + /* Switches to high speed.*/ + sdc_lld_set_data_clk(sdcp); + + /* Selects the card for operations.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SEL_DESEL_CARD, + sdcp->rca, resp)) + goto failed; + + /* Block length fixed at 512 bytes.*/ + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BLOCKLEN, + MMCSD_BLOCK_SIZE, resp) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + + /* Switches to wide bus mode.*/ + switch (sdcp->cardmode & SDC_MODE_CARDTYPE_MASK) { + case SDC_MODE_CARDTYPE_SDV11: + case SDC_MODE_CARDTYPE_SDV20: + sdc_lld_set_bus_mode(sdcp, SDC_MODE_4BIT); + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_APP_CMD, sdcp->rca, resp) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + if (sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_SET_BUS_WIDTH, 2, resp) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + break; + } + + /* Determine capacity.*/ + sdcp->capacity = mmcsdGetCapacity(sdcp->csd); + if (sdcp->capacity == 0) + goto failed; + + /* Initialization complete.*/ + sdcp->state = BLK_READY; + return HAL_SUCCESS; + + /* Connection failed, state reset to BLK_ACTIVE.*/ +failed: + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_FAILED; +} + +/** + * @brief Brings the driver in a state safe for card removal. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcDisconnect(SDCDriver *sdcp) { + + osalDbgCheck(sdcp != NULL); + + osalSysLock(); + osalDbgAssert((sdcp->state == BLK_ACTIVE) || (sdcp->state == BLK_READY), + "invalid state"); + if (sdcp->state == BLK_ACTIVE) { + osalSysUnlock(); + return HAL_SUCCESS; + } + sdcp->state = BLK_DISCONNECTING; + osalSysUnlock(); + + /* Waits for eventual pending operations completion.*/ + if (_sdc_wait_for_transfer_state(sdcp)) { + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_FAILED; + } + + /* Card clock stopped.*/ + sdc_lld_stop_clk(sdcp); + sdcp->state = BLK_ACTIVE; + return HAL_SUCCESS; +} + +/** + * @brief Reads one or more blocks. + * @pre The driver must be in the @p BLK_READY state after a successful + * sdcConnect() invocation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to read + * @param[out] buf pointer to the read buffer + * @param[in] n number of blocks to read + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcRead(SDCDriver *sdcp, uint32_t startblk, uint8_t *buf, uint32_t n) { + bool status; + + osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + if ((startblk + n - 1) > sdcp->capacity){ + sdcp->errors |= SDC_OVERFLOW_ERROR; + return HAL_FAILED; + } + + /* Read operation in progress.*/ + sdcp->state = BLK_READING; + + status = sdc_lld_read(sdcp, startblk, buf, n); + + /* Read operation finished.*/ + sdcp->state = BLK_READY; + return status; +} + +/** + * @brief Writes one or more blocks. + * @pre The driver must be in the @p BLK_READY state after a successful + * sdcConnect() invocation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk first block to write + * @param[out] buf pointer to the write buffer + * @param[in] n number of blocks to write + * + * @return The operation status. + * @retval HAL_SUCCESS operation succeeded. + * @retval HAL_FAILED operation failed. + * + * @api + */ +bool sdcWrite(SDCDriver *sdcp, uint32_t startblk, + const uint8_t *buf, uint32_t n) { + bool status; + + osalDbgCheck((sdcp != NULL) && (buf != NULL) && (n > 0)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + if ((startblk + n - 1) > sdcp->capacity){ + sdcp->errors |= SDC_OVERFLOW_ERROR; + return HAL_FAILED; + } + + /* Write operation in progress.*/ + sdcp->state = BLK_WRITING; + + status = sdc_lld_write(sdcp, startblk, buf, n); + + /* Write operation finished.*/ + sdcp->state = BLK_READY; + return status; +} + +/** + * @brief Returns the errors mask associated to the previous operation. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @return The errors mask. + * + * @api + */ +sdcflags_t sdcGetAndClearErrors(SDCDriver *sdcp) { + sdcflags_t flags; + + osalDbgCheck(sdcp != NULL); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + osalSysLock(); + flags = sdcp->errors; + sdcp->errors = SDC_NO_ERROR; + osalSysUnlock(); + return flags; +} + +/** + * @brief Waits for card idle condition. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcSync(SDCDriver *sdcp) { + bool result; + + osalDbgCheck(sdcp != NULL); + + if (sdcp->state != BLK_READY) + return HAL_FAILED; + + /* Synchronization operation in progress.*/ + sdcp->state = BLK_SYNCING; + + result = sdc_lld_sync(sdcp); + + /* Synchronization operation finished.*/ + sdcp->state = BLK_READY; + return result; +} + +/** + * @brief Returns the media info. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[out] bdip pointer to a @p BlockDeviceInfo structure + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcGetInfo(SDCDriver *sdcp, BlockDeviceInfo *bdip) { + + osalDbgCheck((sdcp != NULL) && (bdip != NULL)); + + if (sdcp->state != BLK_READY) + return HAL_FAILED; + + bdip->blk_num = sdcp->capacity; + bdip->blk_size = MMCSD_BLOCK_SIZE; + + return HAL_SUCCESS; +} + + +/** + * @brief Erases the supplied blocks. + * + * @param[in] sdcp pointer to the @p SDCDriver object + * @param[in] startblk starting block number + * @param[in] endblk ending block number + * + * @return The operation status. + * @retval HAL_SUCCESS the operation succeeded. + * @retval HAL_FAILED the operation failed. + * + * @api + */ +bool sdcErase(SDCDriver *sdcp, uint32_t startblk, uint32_t endblk) { + uint32_t resp[1]; + + osalDbgCheck((sdcp != NULL)); + osalDbgAssert(sdcp->state == BLK_READY, "invalid state"); + + /* Erase operation in progress.*/ + sdcp->state = BLK_WRITING; + + /* Handling command differences between HC and normal cards.*/ + if (!(sdcp->cardmode & SDC_MODE_HIGH_CAPACITY)) { + startblk *= MMCSD_BLOCK_SIZE; + endblk *= MMCSD_BLOCK_SIZE; + } + + _sdc_wait_for_transfer_state(sdcp); + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_START, + startblk, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE_RW_BLK_END, + endblk, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + + if ((sdc_lld_send_cmd_short_crc(sdcp, MMCSD_CMD_ERASE, + 0, resp) != HAL_SUCCESS) || + MMCSD_R1_ERROR(resp[0])) + goto failed; + + /* Quick sleep to allow it to transition to programming or receiving state */ + /* TODO: ??????????????????????????? */ + + /* Wait for it to return to transfer state to indicate it has finished erasing */ + _sdc_wait_for_transfer_state(sdcp); + + sdcp->state = BLK_READY; + return HAL_SUCCESS; + +failed: + sdcp->state = BLK_READY; + return HAL_FAILED; +} + +#endif /* HAL_USE_SDC */ + +/** @} */ -- cgit v1.2.3 From be933e612987ad4d0888b4baca5ba2328b4a2dd6 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 Sep 2013 12:25:11 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6308 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/sdc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c index 48d181549..d18f37b55 100644 --- a/os/hal/src/sdc.c +++ b/os/hal/src/sdc.c @@ -86,7 +86,7 @@ bool _sdc_wait_for_transfer_state(SDCDriver *sdcp) { case MMCSD_STS_RCV: case MMCSD_STS_PRG: #if SDC_NICE_WAITING - osalThreadSleepMilliseconds(1); + osalThreadSleep(MS2ST(1)); #endif continue; default: @@ -257,7 +257,7 @@ bool sdcConnect(SDCDriver *sdcp) { } if (++i >= SDC_INIT_RETRY) goto failed; - osalThreadSleepMilliseconds(10); + osalThreadSleep(MS2ST(10)); } } -- cgit v1.2.3 From 18fe69dbb27e1e9530d459c625ce6d3b623b8255 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 28 Sep 2013 08:28:52 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6326 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c index 8b56b4ac8..7b6dc4640 100644 --- a/os/hal/src/hal.c +++ b/os/hal/src/hal.c @@ -65,9 +65,6 @@ void halInit(void) { /* Platform low level initializations.*/ hal_lld_init(); -#if HAL_USE_TM || defined(__DOXYGEN__) - tmInit(); -#endif #if HAL_USE_PAL || defined(__DOXYGEN__) palInit(&pal_default_config); #endif -- cgit v1.2.3 From 1b6619e5ccd8ee5a28968c5e703b334ce3738d7a Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 14 Nov 2013 11:01:51 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6474 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/can.c | 12 ++++++------ os/hal/src/hal_queues.c | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/can.c b/os/hal/src/can.c index ed5c43f87..92efdf7e7 100644 --- a/os/hal/src/can.c +++ b/os/hal/src/can.c @@ -73,8 +73,8 @@ void canObjectInit(CANDriver *canp) { canp->state = CAN_STOP; canp->config = NULL; - osalQueueObjectInit(&canp->txqueue); - osalQueueObjectInit(&canp->rxqueue); + osalThreadQueueObjectInit(&canp->txqueue); + osalThreadQueueObjectInit(&canp->rxqueue); osalEventObjectInit(&canp->rxfull_event); osalEventObjectInit(&canp->txempty_event); osalEventObjectInit(&canp->error_event); @@ -131,8 +131,8 @@ void canStop(CANDriver *canp) { "invalid state"); can_lld_stop(canp); canp->state = CAN_STOP; - osalQueueWakeupAllI(&canp->rxqueue, MSG_RESET); - osalQueueWakeupAllI(&canp->txqueue, MSG_RESET); + osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET); + osalThreadDequeueAllI(&canp->txqueue, MSG_RESET); osalOsRescheduleS(); osalSysUnlock(); } @@ -170,7 +170,7 @@ msg_t canTransmit(CANDriver *canp, osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { - msg_t msg = osalQueueGoSleepTimeoutS(&canp->txqueue, timeout); + msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; @@ -215,7 +215,7 @@ msg_t canReceive(CANDriver *canp, osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { - msg_t msg = osalQueueGoSleepTimeoutS(&canp->rxqueue, timeout); + msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; diff --git a/os/hal/src/hal_queues.c b/os/hal/src/hal_queues.c index 52b9daf6c..dac58a155 100644 --- a/os/hal/src/hal_queues.c +++ b/os/hal/src/hal_queues.c @@ -62,7 +62,7 @@ void iqObjectInit(input_queue_t *iqp, uint8_t *bp, size_t size, qnotify_t infy, void *link) { - osalQueueObjectInit(&iqp->q_waiting); + osalThreadQueueObjectInit(&iqp->q_waiting); iqp->q_counter = 0; iqp->q_buffer = iqp->q_rdptr = iqp->q_wrptr = bp; iqp->q_top = bp + size; @@ -87,7 +87,7 @@ void iqResetI(input_queue_t *iqp) { iqp->q_rdptr = iqp->q_wrptr = iqp->q_buffer; iqp->q_counter = 0; - osalQueueWakeupAllI(&iqp->q_waiting, Q_RESET); + osalThreadDequeueAllI(&iqp->q_waiting, Q_RESET); } /** @@ -115,7 +115,7 @@ msg_t iqPutI(input_queue_t *iqp, uint8_t b) { if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; - osalQueueWakeupOneI(&iqp->q_waiting, Q_OK); + osalThreadDequeueNextI(&iqp->q_waiting, Q_OK); return Q_OK; } @@ -149,7 +149,7 @@ msg_t iqGetTimeout(input_queue_t *iqp, systime_t time) { while (iqIsEmptyI(iqp)) { msg_t msg; - if ((msg = osalQueueGoSleepTimeoutS(&iqp->q_waiting, time)) < Q_OK) { + if ((msg = osalThreadEnqueueTimeoutS(&iqp->q_waiting, time)) < Q_OK) { osalSysUnlock(); return msg; } @@ -201,7 +201,7 @@ size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp, nfy(iqp); while (iqIsEmptyI(iqp)) { - if (osalQueueGoSleepTimeoutS(&iqp->q_waiting, time) != Q_OK) { + if (osalThreadEnqueueTimeoutS(&iqp->q_waiting, time) != Q_OK) { osalSysUnlock(); return r; } @@ -240,7 +240,7 @@ size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp, void oqObjectInit(output_queue_t *oqp, uint8_t *bp, size_t size, qnotify_t onfy, void *link) { - osalQueueObjectInit(&oqp->q_waiting); + osalThreadQueueObjectInit(&oqp->q_waiting); oqp->q_counter = size; oqp->q_buffer = oqp->q_rdptr = oqp->q_wrptr = bp; oqp->q_top = bp + size; @@ -265,7 +265,7 @@ void oqResetI(output_queue_t *oqp) { oqp->q_rdptr = oqp->q_wrptr = oqp->q_buffer; oqp->q_counter = qSizeI(oqp); - osalQueueWakeupAllI(&oqp->q_waiting, Q_RESET); + osalThreadDequeueAllI(&oqp->q_waiting, Q_RESET); } /** @@ -296,7 +296,7 @@ msg_t oqPutTimeout(output_queue_t *oqp, uint8_t b, systime_t time) { while (oqIsFullI(oqp)) { msg_t msg; - if ((msg = osalQueueGoSleepTimeoutS(&oqp->q_waiting, time)) < Q_OK) { + if ((msg = osalThreadEnqueueTimeoutS(&oqp->q_waiting, time)) < Q_OK) { osalSysUnlock(); return msg; } @@ -337,7 +337,7 @@ msg_t oqGetI(output_queue_t *oqp) { if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; - osalQueueWakeupOneI(&oqp->q_waiting, Q_OK); + osalThreadDequeueNextI(&oqp->q_waiting, Q_OK); return b; } @@ -376,7 +376,7 @@ size_t oqWriteTimeout(output_queue_t *oqp, const uint8_t *bp, osalSysLock(); while (TRUE) { while (oqIsFullI(oqp)) { - if (osalQueueGoSleepTimeoutS(&oqp->q_waiting, time) != Q_OK) { + if (osalThreadEnqueueTimeoutS(&oqp->q_waiting, time) != Q_OK) { osalSysUnlock(); return w; } -- cgit v1.2.3 From fc91e8bea11e9e24684f39d69cceda6c2e2dd2d0 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 26 Nov 2013 08:12:01 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6511 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'os/hal/src') diff --git a/os/hal/src/i2c.c b/os/hal/src/i2c.c index 3e037332b..ba349457d 100644 --- a/os/hal/src/i2c.c +++ b/os/hal/src/i2c.c @@ -245,7 +245,7 @@ msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, #if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) /** * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the SPI bus, if the bus + * @details This function tries to gain ownership to the I2C bus, if the bus * is already being used then the invoking thread is queued. * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION * must be enabled. -- cgit v1.2.3 From 151ca1d309f2d350527a73676c5aa47f5c2fa921 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 20 Jan 2014 12:26:50 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6634 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/st.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'os/hal/src') diff --git a/os/hal/src/st.c b/os/hal/src/st.c index f2e8f3bf2..afb4466fa 100644 --- a/os/hal/src/st.c +++ b/os/hal/src/st.c @@ -66,6 +66,71 @@ void stInit(void) { st_lld_init(); } + +/** + * @brief Starts the alarm. + * @note Makes sure that no spurious alarms are triggered after + * this call. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] time the time to be set for the first alarm + * + * @api + */ +void stStartAlarm(systime_t time) { + + osalDbgAssert(stIsAlarmActive() == false, "already active"); + + st_lld_start_alarm(time); +} + +/** + * @brief Stops the alarm interrupt. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @api + */ +void stStopAlarm(void) { + + osalDbgAssert(stIsAlarmActive() != false, "not active"); + + st_lld_stop_alarm(); +} + +/** + * @brief Sets the alarm time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @param[in] time the time to be set for the next alarm + * + * @api + */ +void stSetAlarm(systime_t time) { + + osalDbgAssert(stIsAlarmActive() != false, "not active"); + + st_lld_set_alarm(time); +} + +/** + * @brief Returns the current alarm time. + * @note This functionality is only available in free running mode, the + * behavior in periodic mode is undefined. + * + * @return The currently set alarm time. + * + * @api + */ +systime_t stGetAlarm(void) { + + osalDbgAssert(stIsAlarmActive() != false, "not active"); + + return st_lld_get_alarm(); +} + #endif /* OSAL_ST_MODE != OSAL_ST_MODE_NONE */ /** @} */ -- cgit v1.2.3 From 57d5ba67c58f5226a9ddc8c58a01c29d71772c08 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Feb 2014 15:45:58 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6672 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/sdc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'os/hal/src') diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c index d18f37b55..c75397291 100644 --- a/os/hal/src/sdc.c +++ b/os/hal/src/sdc.c @@ -200,6 +200,9 @@ bool sdcConnect(SDCDriver *sdcp) { /* Card clock initialization.*/ sdc_lld_start_clk(sdcp); + /* Clock activation delay.*/ + osalThreadSleep(MS2ST(STM32_SDC_CLOCK_ACTIVATION_DELAY)); + /* Enforces the initial card state.*/ sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); -- cgit v1.2.3 From 58fd763110ba6c1c45d137e5be7321a12dfc9063 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Feb 2014 15:50:16 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6673 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/sdc.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/sdc.c b/os/hal/src/sdc.c index c75397291..d18f37b55 100644 --- a/os/hal/src/sdc.c +++ b/os/hal/src/sdc.c @@ -200,9 +200,6 @@ bool sdcConnect(SDCDriver *sdcp) { /* Card clock initialization.*/ sdc_lld_start_clk(sdcp); - /* Clock activation delay.*/ - osalThreadSleep(MS2ST(STM32_SDC_CLOCK_ACTIVATION_DELAY)); - /* Enforces the initial card state.*/ sdc_lld_send_cmd_none(sdcp, MMCSD_CMD_GO_IDLE_STATE, 0); -- cgit v1.2.3 From 27261ab8a6ade925246c1dec80ead3f4a9c651c2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 16 Feb 2014 09:12:08 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6715 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/hal.c | 3 ++ os/hal/src/i2s.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 os/hal/src/i2s.c (limited to 'os/hal/src') diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c index 7b6dc4640..aa3eca165 100644 --- a/os/hal/src/hal.c +++ b/os/hal/src/hal.c @@ -83,6 +83,9 @@ void halInit(void) { #if HAL_USE_I2C || defined(__DOXYGEN__) i2cInit(); #endif +#if HAL_USE_I2S || defined(__DOXYGEN__) + i2sInit(); +#endif #if HAL_USE_ICU || defined(__DOXYGEN__) icuInit(); #endif diff --git a/os/hal/src/i2s.c b/os/hal/src/i2s.c new file mode 100644 index 000000000..e2b51ec98 --- /dev/null +++ b/os/hal/src/i2s.c @@ -0,0 +1,159 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file i2s.c + * @brief I2S Driver code. + * + * @addtogroup I2S + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2S || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2S Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2sInit(void) { + + i2s_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2SDriver structure. + * + * @param[out] i2sp pointer to the @p I2SDriver object + * + * @init + */ +void i2sObjectInit(I2SDriver *i2sp) { + + i2sp->state = I2S_STOP; + i2sp->config = NULL; +} + +/** + * @brief Configures and activates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * @param[in] config pointer to the @p I2SConfig object + * + * @api + */ +void i2sStart(I2SDriver *i2sp, const I2SConfig *config) { + + osalDbgCheck((i2sp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), + "invalid state"); + i2sp->config = config; + i2s_lld_start(i2sp); + i2sp->state = I2S_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the I2S peripheral. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStop(I2SDriver *i2sp) { + + osalDbgCheck(i2sp != NULL); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_STOP) || (i2sp->state == I2S_READY), + "invalid state"); + i2s_lld_stop(i2sp); + i2sp->state = I2S_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts a I2S data exchange. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStartExchange(I2SDriver *i2sp) { + + osalDbgCheck(i2sp != NULL); + + osalSysLock(); + osalDbgAssert(i2sp->state == I2S_READY, "not ready"); + i2sStartExchangeI(i2sp); + osalSysUnlock(); +} + +/** + * @brief Stops the ongoing data exchange. + * @details The ongoing data exchange, if any, is stopped, if the driver + * was not active the function does nothing. + * + * @param[in] i2sp pointer to the @p I2SDriver object + * + * @api + */ +void i2sStopExchange(I2SDriver *i2sp) { + + osalDbgCheck((i2sp != NULL)); + + osalSysLock(); + osalDbgAssert((i2sp->state == I2S_READY) || + (i2sp->state == I2S_ACTIVE) || + (i2sp->state == I2S_COMPLETE), + "invalid state"); + i2sStopExchangeI(i2sp); + osalSysUnlock(); +} + +#endif /* HAL_USE_I2S */ + +/** @} */ -- cgit v1.2.3 From 590c1329a400a67c937b30dd55c58210549348b5 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 5 Mar 2014 10:24:50 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6753 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/dac.c | 2343 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2343 insertions(+) create mode 100644 os/hal/src/dac.c (limited to 'os/hal/src') diff --git a/os/hal/src/dac.c b/os/hal/src/dac.c new file mode 100644 index 000000000..ae1667cbe --- /dev/null +++ b/os/hal/src/dac.c @@ -0,0 +1,2343 @@ + + + + + + + + + + + ChibiOS/os/hal/src/dac.c at dac-3.0 · mobyfab/ChibiOS · GitHub + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+
+ + + + + + + +
+ + +
+ + + + + +
+ + This repository + + + +
+ + + + + + + + +
+
+ +
+
+ + + + +
+ +
+
+ + + + +

+ public + + + + + / + ChibiOS + + + Octocat-spinner-32 + + + + forked from mabl/ChibiOS + +

+
+
+ +
+
+
+ + +
+
+ +
+ + + +
+
+ +
+ + + + +
+

HTTPS clone URL

+
+ + + +
+
+ + + +
+

Subversion checkout URL

+
+ + + +
+
+ + +

You can clone with + HTTPS + or Subversion. + + + + + +

+ + + + + Clone in Desktop + + + + + Download ZIP + +
+
+ +
+ + + + + + + + + +
+ + +
+ + + branch: + dac-3.0 + + + +
+ + +
+ + +
+ Fetching contributors… + +
+

Octocat-spinner-32-eaf2f5

+

Cannot retrieve contributors at this time

+
+
+ +
+
+
+
+ + file + + 325 lines (281 sloc) + + 10.304 kb +
+ +
+
+ + + + + +
+ 1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 + +
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012 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 dac.c
* @brief DAC Driver code.
*
* @addtogroup DAC
* @{
*/

#include "hal.h"

#if HAL_USE_DAC || defined(__DOXYGEN__)

/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/

/**
* @brief DAC Driver initialization.
* @note This function is implicitly invoked by @p halInit(), there is
* no need to explicitly initialize the driver.
*
* @init
*/
void dacInit(void) {

  dac_lld_init();
}

/**
* @brief Initializes the standard part of a @p DACDriver structure.
*
* @param[out] dacp pointer to the @p DACDriver object
*
* @init
*/
void dacObjectInit(DACDriver *dacp) {

  dacp->state = DAC_STOP;
  dacp->config = NULL;
#if DAC_USE_WAIT
  dacp->thread = NULL;
#endif /* DAC_USE_WAIT */
#if DAC_USE_MUTUAL_EXCLUSION
  osalMutexObjectInit(&dacp->mutex);
#endif /* DAC_USE_MUTUAL_EXCLUSION */
#if defined(DAC_DRIVER_EXT_INIT_HOOK)
  DAC_DRIVER_EXT_INIT_HOOK(dacp);
#endif
}

/**
* @brief Configures and activates the DAC peripheral.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] config pointer to the @p DACConfig object
*
* @api
*/
void dacStart(DACDriver *dacp, const DACConfig *config) {

  osalDbgCheck((dacp != NULL) && (config != NULL));

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
              "invalid state");
  dacp->config = config;
  dac_lld_start(dacp);
  dacp->state = DAC_READY;
  osalSysUnlock();
}

/**
* @brief Deactivates the DAC peripheral.
* @note Deactivating the peripheral also enforces a release of the slave
* select line.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacStop(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
              "invalid state");
  dac_lld_stop(dacp);
  dacp->state = DAC_STOP;
  osalSysUnlock();
}

/**
* @brief Starts a DAC conversion.
* @details Starts an asynchronous conversion operation.
* @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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[in] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
*
* @api
*/
void dacStartConversion(DACDriver *dacp,
                        const DACConversionGroup *grpp,
                        const dacsample_t *samples,
                        size_t depth) {

  osalSysLock();
  dacStartConversionI(dacp, grpp, samples, depth);
  osalSysUnlock();
}

/**
* @brief Starts a DAC 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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[in] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
*
* @iclass
*/
void dacStartConversionI(DACDriver *dacp,
                         const DACConversionGroup *grpp,
                         const dacsample_t *samples,
                         size_t depth) {

  osalDbgCheckClassI();
  osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
             ((depth == 1) || ((depth & 1) == 0)));
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_COMPLETE) ||
              (dacp->state == DAC_ERROR),
              "not ready");

  dacp->samples = samples;
  dacp->depth = depth;
  dacp->grpp = grpp;
  dacp->state = DAC_ACTIVE;
  dac_lld_start_conversion(dacp);
}

/**
* @brief Stops an ongoing conversion.
* @details This function stops the currently ongoing conversion and returns
* the driver in the @p DAC_READY state. If there was no conversion
* being processed then the function does nothing.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacStopConversion(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_ACTIVE),
              "invalid state");
  if (dacp->state != DAC_READY) {
    dac_lld_stop_conversion(dacp);
    dacp->grpp = NULL;
    dacp->state = DAC_READY;
    _dac_reset_s(dacp);
  }
  osalSysUnlock();
}

/**
* @brief Stops an ongoing conversion.
* @details This function stops the currently ongoing conversion and returns
* the driver in the @p DAC_READY state. If there was no conversion
* being processed then the function does nothing.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @iclass
*/
void dacStopConversionI(DACDriver *dacp) {

  osalDbgCheckClassI();
  osalDbgCheck(dacp != NULL);
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_ACTIVE) ||
              (dacp->state == DAC_COMPLETE),
              "invalid state");

  if (dacp->state != DAC_READY) {
    dac_lld_stop_conversion(dacp);
    dacp->grpp = NULL;
    dacp->state = DAC_READY;
    _dac_reset_i(dacp);
  }
}

#if DAC_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Performs a DAC conversion.
* @details Performs a synchronous conversion operation.
* @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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[out] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
* @return The operation result.
* @retval RDY_OK Conversion finished.
* @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
*/
msg_t dacConvert(DACDriver *dacp,
                 const DACConversionGroup *grpp,
                 const dacsample_t *samples,
                 size_t depth) {
  msg_t msg;

  osalSysLock();
  osalDbgAssert(dacp->thread == NULL, "already waiting");
  dacStartConversionI(dacp, grpp, samples, depth);
  msg = osalThreadSuspendS(&dacp->thread);
  osalSysUnlock();
  return msg;
}
#endif /* DAC_USE_WAIT */

#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Gains exclusive access to the DAC bus.
* @details This function tries to gain ownership to the DAC bus, if the bus
* is already being used then the invoking thread is queued.
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacAcquireBus(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalMutexLock(&dacp->mutex);
}

/**
* @brief Releases exclusive access to the DAC bus.
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacReleaseBus(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalMutexUnlock(&dacp->mutex);
}
#endif /* DAC_USE_MUTUAL_EXCLUSION */

#endif /* HAL_USE_DAC */

/** @} */
+
+ +
+
+ + + + +
+ +
+ +
+
+ + +
+ +
+ +
+ + +
+
+
+ +
+
+ +
+ + + +
+ + + Something went wrong with that request. Please try again. +
+ + + + -- cgit v1.2.3 From a6224d1964ef80a53500bde178d639c12dda98ee Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 5 Mar 2014 10:30:58 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6754 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/dac.c | 2667 +++++++----------------------------------------------- 1 file changed, 324 insertions(+), 2343 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/dac.c b/os/hal/src/dac.c index ae1667cbe..92297e520 100644 --- a/os/hal/src/dac.c +++ b/os/hal/src/dac.c @@ -1,2343 +1,324 @@ - - - - - - - - - - - ChibiOS/os/hal/src/dac.c at dac-3.0 · mobyfab/ChibiOS · GitHub - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
-
- - - - - - - -
- - -
- - - - - -
- - This repository - - - -
- - - - - - - - -
-
- -
-
- - - - -
- -
-
- - - - -

- public - - - - - / - ChibiOS - - - Octocat-spinner-32 - - - - forked from mabl/ChibiOS - -

-
-
- -
-
-
- - -
-
- -
- - - -
-
- -
- - - - -
-

HTTPS clone URL

-
- - - -
-
- - - -
-

Subversion checkout URL

-
- - - -
-
- - -

You can clone with - HTTPS - or Subversion. - - - - - -

- - - - - Clone in Desktop - - - - - Download ZIP - -
-
- -
- - - - - - - - - -
- - -
- - - branch: - dac-3.0 - - - -
- - -
- - -
- Fetching contributors… - -
-

Octocat-spinner-32-eaf2f5

-

Cannot retrieve contributors at this time

-
-
- -
-
-
-
- - file - - 325 lines (281 sloc) - - 10.304 kb -
- -
-
- - - - - -
- 1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 - -
/*
ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
2011,2012 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 dac.c
* @brief DAC Driver code.
*
* @addtogroup DAC
* @{
*/

#include "hal.h"

#if HAL_USE_DAC || defined(__DOXYGEN__)

/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/

/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/

/**
* @brief DAC Driver initialization.
* @note This function is implicitly invoked by @p halInit(), there is
* no need to explicitly initialize the driver.
*
* @init
*/
void dacInit(void) {

  dac_lld_init();
}

/**
* @brief Initializes the standard part of a @p DACDriver structure.
*
* @param[out] dacp pointer to the @p DACDriver object
*
* @init
*/
void dacObjectInit(DACDriver *dacp) {

  dacp->state = DAC_STOP;
  dacp->config = NULL;
#if DAC_USE_WAIT
  dacp->thread = NULL;
#endif /* DAC_USE_WAIT */
#if DAC_USE_MUTUAL_EXCLUSION
  osalMutexObjectInit(&dacp->mutex);
#endif /* DAC_USE_MUTUAL_EXCLUSION */
#if defined(DAC_DRIVER_EXT_INIT_HOOK)
  DAC_DRIVER_EXT_INIT_HOOK(dacp);
#endif
}

/**
* @brief Configures and activates the DAC peripheral.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] config pointer to the @p DACConfig object
*
* @api
*/
void dacStart(DACDriver *dacp, const DACConfig *config) {

  osalDbgCheck((dacp != NULL) && (config != NULL));

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
              "invalid state");
  dacp->config = config;
  dac_lld_start(dacp);
  dacp->state = DAC_READY;
  osalSysUnlock();
}

/**
* @brief Deactivates the DAC peripheral.
* @note Deactivating the peripheral also enforces a release of the slave
* select line.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacStop(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY),
              "invalid state");
  dac_lld_stop(dacp);
  dacp->state = DAC_STOP;
  osalSysUnlock();
}

/**
* @brief Starts a DAC conversion.
* @details Starts an asynchronous conversion operation.
* @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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[in] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
*
* @api
*/
void dacStartConversion(DACDriver *dacp,
                        const DACConversionGroup *grpp,
                        const dacsample_t *samples,
                        size_t depth) {

  osalSysLock();
  dacStartConversionI(dacp, grpp, samples, depth);
  osalSysUnlock();
}

/**
* @brief Starts a DAC 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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[in] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
*
* @iclass
*/
void dacStartConversionI(DACDriver *dacp,
                         const DACConversionGroup *grpp,
                         const dacsample_t *samples,
                         size_t depth) {

  osalDbgCheckClassI();
  osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
             ((depth == 1) || ((depth & 1) == 0)));
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_COMPLETE) ||
              (dacp->state == DAC_ERROR),
              "not ready");

  dacp->samples = samples;
  dacp->depth = depth;
  dacp->grpp = grpp;
  dacp->state = DAC_ACTIVE;
  dac_lld_start_conversion(dacp);
}

/**
* @brief Stops an ongoing conversion.
* @details This function stops the currently ongoing conversion and returns
* the driver in the @p DAC_READY state. If there was no conversion
* being processed then the function does nothing.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacStopConversion(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalSysLock();
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_ACTIVE),
              "invalid state");
  if (dacp->state != DAC_READY) {
    dac_lld_stop_conversion(dacp);
    dacp->grpp = NULL;
    dacp->state = DAC_READY;
    _dac_reset_s(dacp);
  }
  osalSysUnlock();
}

/**
* @brief Stops an ongoing conversion.
* @details This function stops the currently ongoing conversion and returns
* the driver in the @p DAC_READY state. If there was no conversion
* being processed then the function does nothing.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @iclass
*/
void dacStopConversionI(DACDriver *dacp) {

  osalDbgCheckClassI();
  osalDbgCheck(dacp != NULL);
  osalDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_ACTIVE) ||
              (dacp->state == DAC_COMPLETE),
              "invalid state");

  if (dacp->state != DAC_READY) {
    dac_lld_stop_conversion(dacp);
    dacp->grpp = NULL;
    dacp->state = DAC_READY;
    _dac_reset_i(dacp);
  }
}

#if DAC_USE_WAIT || defined(__DOXYGEN__)
/**
* @brief Performs a DAC conversion.
* @details Performs a synchronous conversion operation.
* @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
* with no gaps.
*
* @param[in] dacp pointer to the @p DACDriver object
* @param[in] grpp pointer to a @p DACConversionGroup object
* @param[out] samples pointer to the samples buffer
* @param[in] depth buffer depth (matrix rows number). The buffer depth
* must be one or an even number.
* @return The operation result.
* @retval RDY_OK Conversion finished.
* @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
*/
msg_t dacConvert(DACDriver *dacp,
                 const DACConversionGroup *grpp,
                 const dacsample_t *samples,
                 size_t depth) {
  msg_t msg;

  osalSysLock();
  osalDbgAssert(dacp->thread == NULL, "already waiting");
  dacStartConversionI(dacp, grpp, samples, depth);
  msg = osalThreadSuspendS(&dacp->thread);
  osalSysUnlock();
  return msg;
}
#endif /* DAC_USE_WAIT */

#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Gains exclusive access to the DAC bus.
* @details This function tries to gain ownership to the DAC bus, if the bus
* is already being used then the invoking thread is queued.
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacAcquireBus(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalMutexLock(&dacp->mutex);
}

/**
* @brief Releases exclusive access to the DAC bus.
* @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION
* must be enabled.
*
* @param[in] dacp pointer to the @p DACDriver object
*
* @api
*/
void dacReleaseBus(DACDriver *dacp) {

  osalDbgCheck(dacp != NULL);

  osalMutexUnlock(&dacp->mutex);
}
#endif /* DAC_USE_MUTUAL_EXCLUSION */

#endif /* HAL_USE_DAC */

/** @} */
-
- -
-
- - - - -
- -
- -
-
- - -
- -
- -
- - -
-
-
- -
-
- -
- - - -
- - - Something went wrong with that request. Please try again. -
- - - - +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012 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 . +*/ + +/** + * @file dac.c + * @brief DAC Driver code. + * + * @addtogroup DAC + * @{ + */ + +#include "hal.h" + +#if HAL_USE_DAC || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief DAC Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void dacInit(void) { + + dac_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p DACDriver structure. + * + * @param[out] dacp pointer to the @p DACDriver object + * + * @init + */ +void dacObjectInit(DACDriver *dacp) { + + dacp->state = DAC_STOP; + dacp->config = NULL; +#if DAC_USE_WAIT + dacp->thread = NULL; +#endif /* DAC_USE_WAIT */ +#if DAC_USE_MUTUAL_EXCLUSION + osalMutexObjectInit(&dacp->mutex); +#endif /* DAC_USE_MUTUAL_EXCLUSION */ +#if defined(DAC_DRIVER_EXT_INIT_HOOK) + DAC_DRIVER_EXT_INIT_HOOK(dacp); +#endif +} + +/** + * @brief Configures and activates the DAC peripheral. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] config pointer to the @p DACConfig object + * + * @api + */ +void dacStart(DACDriver *dacp, const DACConfig *config) { + + osalDbgCheck((dacp != NULL) && (config != NULL)); + + osalSysLock(); + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), + "invalid state"); + dacp->config = config; + dac_lld_start(dacp); + dacp->state = DAC_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the DAC peripheral. + * @note Deactivating the peripheral also enforces a release of the slave + * select line. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacStop(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalSysLock(); + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), + "invalid state"); + dac_lld_stop(dacp); + dacp->state = DAC_STOP; + osalSysUnlock(); +} + +/** + * @brief Starts a DAC conversion. + * @details Starts an asynchronous conversion operation. + * @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 + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[in] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @api + */ +void dacStartConversion(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + + osalSysLock(); + dacStartConversionI(dacp, grpp, samples, depth); + osalSysUnlock(); +} + +/** + * @brief Starts a DAC 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 + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[in] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * + * @iclass + */ +void dacStartConversionI(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + + osalDbgCheckClassI(); + osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && + ((depth == 1) || ((depth & 1) == 0))); + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_COMPLETE) || + (dacp->state == DAC_ERROR), + "not ready"); + + dacp->samples = samples; + dacp->depth = depth; + dacp->grpp = grpp; + dacp->state = DAC_ACTIVE; + dac_lld_start_conversion(dacp); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p DAC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacStopConversion(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalSysLock(); + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_ACTIVE), + "invalid state"); + if (dacp->state != DAC_READY) { + dac_lld_stop_conversion(dacp); + dacp->grpp = NULL; + dacp->state = DAC_READY; + _dac_reset_s(dacp); + } + osalSysUnlock(); +} + +/** + * @brief Stops an ongoing conversion. + * @details This function stops the currently ongoing conversion and returns + * the driver in the @p DAC_READY state. If there was no conversion + * being processed then the function does nothing. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @iclass + */ +void dacStopConversionI(DACDriver *dacp) { + + osalDbgCheckClassI(); + osalDbgCheck(dacp != NULL); + osalDbgAssert((dacp->state == DAC_READY) || + (dacp->state == DAC_ACTIVE) || + (dacp->state == DAC_COMPLETE), + "invalid state"); + + if (dacp->state != DAC_READY) { + dac_lld_stop_conversion(dacp); + dacp->grpp = NULL; + dacp->state = DAC_READY; + _dac_reset_i(dacp); + } +} + +#if DAC_USE_WAIT || defined(__DOXYGEN__) +/** + * @brief Performs a DAC conversion. + * @details Performs a synchronous conversion operation. + * @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 + * with no gaps. + * + * @param[in] dacp pointer to the @p DACDriver object + * @param[in] grpp pointer to a @p DACConversionGroup object + * @param[out] samples pointer to the samples buffer + * @param[in] depth buffer depth (matrix rows number). The buffer depth + * must be one or an even number. + * @return The operation result. + * @retval RDY_OK Conversion finished. + * @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 + */ +msg_t dacConvert(DACDriver *dacp, + const DACConversionGroup *grpp, + const dacsample_t *samples, + size_t depth) { + msg_t msg; + + osalSysLock(); + osalDbgAssert(dacp->thread == NULL, "already waiting"); + dacStartConversionI(dacp, grpp, samples, depth); + msg = osalThreadSuspendS(&dacp->thread); + osalSysUnlock(); + return msg; +} +#endif /* DAC_USE_WAIT */ + +#if DAC_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the DAC bus. + * @details This function tries to gain ownership to the DAC bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacAcquireBus(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalMutexLock(&dacp->mutex); +} + +/** + * @brief Releases exclusive access to the DAC bus. + * @pre In order to use this function the option @p DAC_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] dacp pointer to the @p DACDriver object + * + * @api + */ +void dacReleaseBus(DACDriver *dacp) { + + osalDbgCheck(dacp != NULL); + + osalMutexUnlock(&dacp->mutex); +} +#endif /* DAC_USE_MUTUAL_EXCLUSION */ + +#endif /* HAL_USE_DAC */ + +/** @} */ -- cgit v1.2.3 From bfd29a27c2c977de5b565e48012eb38e6541f15f Mon Sep 17 00:00:00 2001 From: gdisirio Date: Wed, 5 Mar 2014 10:42:18 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6755 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/dac.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/dac.c b/os/hal/src/dac.c index 92297e520..42521c107 100644 --- a/os/hal/src/dac.c +++ b/os/hal/src/dac.c @@ -1,6 +1,6 @@ /* ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012 Giovanni Di Sirio. + 2011,2012,2013 Giovanni Di Sirio. This file is part of ChibiOS/RT. @@ -97,11 +97,14 @@ void dacStart(DACDriver *dacp, const DACConfig *config) { osalDbgCheck((dacp != NULL) && (config != NULL)); osalSysLock(); + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), - "invalid state"); + "invalid state"); + dacp->config = config; dac_lld_start(dacp); dacp->state = DAC_READY; + osalSysUnlock(); } @@ -119,10 +122,13 @@ void dacStop(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalSysLock(); + osalDbgAssert((dacp->state == DAC_STOP) || (dacp->state == DAC_READY), - "invalid state"); + "invalid state"); + dac_lld_stop(dacp); dacp->state = DAC_STOP; + osalSysUnlock(); } @@ -177,11 +183,11 @@ void dacStartConversionI(DACDriver *dacp, osalDbgCheckClassI(); osalDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) && - ((depth == 1) || ((depth & 1) == 0))); + ((depth == 1) || ((depth & 1) == 0))); osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_COMPLETE) || - (dacp->state == DAC_ERROR), - "not ready"); + (dacp->state == DAC_COMPLETE) || + (dacp->state == DAC_ERROR), + "not ready"); dacp->samples = samples; dacp->depth = depth; @@ -205,15 +211,18 @@ void dacStopConversion(DACDriver *dacp) { osalDbgCheck(dacp != NULL); osalSysLock(); + osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_ACTIVE), - "invalid state"); + (dacp->state == DAC_ACTIVE), + "invalid state"); + if (dacp->state != DAC_READY) { dac_lld_stop_conversion(dacp); dacp->grpp = NULL; dacp->state = DAC_READY; _dac_reset_s(dacp); } + osalSysUnlock(); } @@ -232,9 +241,9 @@ void dacStopConversionI(DACDriver *dacp) { osalDbgCheckClassI(); osalDbgCheck(dacp != NULL); osalDbgAssert((dacp->state == DAC_READY) || - (dacp->state == DAC_ACTIVE) || - (dacp->state == DAC_COMPLETE), - "invalid state"); + (dacp->state == DAC_ACTIVE) || + (dacp->state == DAC_COMPLETE), + "invalid state"); if (dacp->state != DAC_READY) { dac_lld_stop_conversion(dacp); @@ -259,11 +268,11 @@ void dacStopConversionI(DACDriver *dacp) { * @param[in] depth buffer depth (matrix rows number). The buffer depth * must be one or an even number. * @return The operation result. - * @retval RDY_OK Conversion finished. - * @retval RDY_RESET The conversion has been stopped using + * @retval MSG_OK Conversion finished. + * @retval MSG_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 + * @retval MSG_TIMEOUT The conversion has been stopped because an hardware * error. * * @api @@ -275,9 +284,10 @@ msg_t dacConvert(DACDriver *dacp, msg_t msg; osalSysLock(); - osalDbgAssert(dacp->thread == NULL, "already waiting"); + dacStartConversionI(dacp, grpp, samples, depth); msg = osalThreadSuspendS(&dacp->thread); + osalSysUnlock(); return msg; } -- cgit v1.2.3 From 6bc9f636b5488434375da0296a3d90285dc1cec4 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Mar 2014 10:19:32 +0000 Subject: More enhancements to the GPT driver. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6759 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/gpt.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c index 780ac407e..d654a3c4a 100644 --- a/os/hal/src/gpt.c +++ b/os/hal/src/gpt.c @@ -118,9 +118,7 @@ void gptStop(GPTDriver *gptp) { /** * @brief Changes the interval of GPT peripheral. * @details This function changes the interval of a running GPT unit. - * @pre The GPT unit must have been activated using @p gptStart(). - * @pre The GPT unit must have been running in continuous mode using - * @p gptStartContinuous(). + * @pre The GPT unit must be running in continuous mode. * @post The GPT unit interval is changed to the new value. * * @param[in] gptp pointer to a @p GPTDriver object -- cgit v1.2.3 From 004c5bac0656683f315cf4baf57c2bb90e9453fb Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 8 Mar 2014 17:41:14 +0000 Subject: GPT is usable without callbacks now (trigger, counter). git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6760 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/gpt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'os/hal/src') diff --git a/os/hal/src/gpt.c b/os/hal/src/gpt.c index d654a3c4a..52bf6610f 100644 --- a/os/hal/src/gpt.c +++ b/os/hal/src/gpt.c @@ -198,6 +198,7 @@ void gptStartOneShotI(GPTDriver *gptp, gptcnt_t interval) { osalDbgCheckClassI(); osalDbgCheck(gptp != NULL); + osalDbgCheck(gptp->config->callback != NULL); osalDbgAssert(gptp->state == GPT_READY, "invalid state"); -- cgit v1.2.3 From 2f7fab8fb348668b5a06bb0ed4f133ea0797029e Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 22 Apr 2014 08:38:11 +0000 Subject: Fixed bug #485. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6873 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/mmc_spi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'os/hal/src') diff --git a/os/hal/src/mmc_spi.c b/os/hal/src/mmc_spi.c index 682ed273b..4ffaecfd4 100644 --- a/os/hal/src/mmc_spi.c +++ b/os/hal/src/mmc_spi.c @@ -447,6 +447,7 @@ bool mmcConnect(MMCDriver *mmcp) { /* Connection procedure in progress.*/ mmcp->state = BLK_CONNECTING; + mmcp->block_addresses = FALSE; /* Slow clock mode and 128 clock pulses.*/ spiStart(mmcp->config->spip, mmcp->config->lscfg); -- cgit v1.2.3 From 91216f24048ae3499ec96d06cd19bbe9a384c9dc Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sat, 26 Apr 2014 09:58:18 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6886 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/usb.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'os/hal/src') diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c index a84702b5b..9b292b7d9 100644 --- a/os/hal/src/usb.c +++ b/os/hal/src/usb.c @@ -623,7 +623,12 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { return; } } - +#if (USB_SET_ADDRESS_ACK_HANDLING == USB_SET_ADDRESS_ACK_HW) + if (usbp->setup[1] == USB_REQ_SET_ADDRESS) { + /* Zero-length packet sent by hardware */ + return; + } +#endif /* Transfer preparation. The request handler must have populated correctly the fields ep0next, ep0n and ep0endcb using the macro usbSetupTransfer().*/ @@ -645,10 +650,14 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { /* No transmission phase, directly receiving the zero sized status packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) usbPrepareReceive(usbp, 0, NULL, 0); osalSysLockFromISR(); usbStartReceiveI(usbp, 0); osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif } } else { @@ -665,10 +674,14 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) { /* No receive phase, directly sending the zero sized status packet.*/ usbp->ep0state = USB_EP0_SENDING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) usbPrepareTransmit(usbp, 0, NULL, 0); osalSysLockFromISR(); usbStartTransmitI(usbp, 0); osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif } } } @@ -705,10 +718,14 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) { case USB_EP0_WAITING_TX0: /* Transmit phase over, receiving the zero sized status packet.*/ usbp->ep0state = USB_EP0_WAITING_STS; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) usbPrepareReceive(usbp, 0, NULL, 0); osalSysLockFromISR(); usbStartReceiveI(usbp, 0); osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif return; case USB_EP0_SENDING_STS: /* Status packet sent, invoking the callback if defined.*/ @@ -745,16 +762,22 @@ 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; +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) usbPrepareTransmit(usbp, 0, NULL, 0); osalSysLockFromISR(); usbStartTransmitI(usbp, 0); osalSysUnlockFromISR(); +#else + usb_lld_end_setup(usbp, ep); +#endif return; case USB_EP0_WAITING_STS: /* Status packet received, it must be zero sized, invoking the callback if defined.*/ +#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW) if (usbGetReceiveTransactionSizeI(usbp, 0) != 0) break; +#endif if (usbp->ep0endcb != NULL) usbp->ep0endcb(usbp); usbp->ep0state = USB_EP0_WAITING_SETUP; -- cgit v1.2.3