From 93a7f918ac72390d2acb309088a109648dcb1bf2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 29 Nov 2009 08:32:04 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1345 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/io/adc.c | 204 ----------------- os/io/adc.h | 66 ------ os/io/can.c | 220 ------------------- os/io/can.h | 61 ------ os/io/include/adc.h | 66 ++++++ os/io/include/can.h | 61 ++++++ os/io/include/mac.h | 89 ++++++++ os/io/include/mii.h | 220 +++++++++++++++++++ os/io/include/mmc_spi.h | 204 +++++++++++++++++ os/io/include/pal.h | 467 +++++++++++++++++++++++++++++++++++++++ os/io/include/serial.h | 193 ++++++++++++++++ os/io/include/spi.h | 76 +++++++ os/io/mac.c | 174 --------------- os/io/mac.h | 89 -------- os/io/mii.c | 37 ---- os/io/mii.h | 220 ------------------- os/io/mmc_spi.c | 572 ------------------------------------------------ os/io/mmc_spi.h | 204 ----------------- os/io/pal.c | 94 -------- os/io/pal.h | 467 --------------------------------------- os/io/serial.c | 197 ----------------- os/io/serial.h | 193 ---------------- os/io/spi.c | 258 ---------------------- os/io/spi.h | 76 ------- os/io/src/adc.c | 204 +++++++++++++++++ os/io/src/can.c | 220 +++++++++++++++++++ os/io/src/mac.c | 174 +++++++++++++++ os/io/src/mii.c | 37 ++++ os/io/src/mmc_spi.c | 572 ++++++++++++++++++++++++++++++++++++++++++++++++ os/io/src/pal.c | 94 ++++++++ os/io/src/serial.c | 197 +++++++++++++++++ os/io/src/spi.c | 258 ++++++++++++++++++++++ 32 files changed, 3132 insertions(+), 3132 deletions(-) delete mode 100644 os/io/adc.c delete mode 100644 os/io/adc.h delete mode 100644 os/io/can.c delete mode 100644 os/io/can.h create mode 100644 os/io/include/adc.h create mode 100644 os/io/include/can.h create mode 100644 os/io/include/mac.h create mode 100644 os/io/include/mii.h create mode 100644 os/io/include/mmc_spi.h create mode 100644 os/io/include/pal.h create mode 100644 os/io/include/serial.h create mode 100644 os/io/include/spi.h delete mode 100644 os/io/mac.c delete mode 100644 os/io/mac.h delete mode 100644 os/io/mii.c delete mode 100644 os/io/mii.h delete mode 100644 os/io/mmc_spi.c delete mode 100644 os/io/mmc_spi.h delete mode 100644 os/io/pal.c delete mode 100644 os/io/pal.h delete mode 100644 os/io/serial.c delete mode 100644 os/io/serial.h delete mode 100644 os/io/spi.c delete mode 100644 os/io/spi.h create mode 100644 os/io/src/adc.c create mode 100644 os/io/src/can.c create mode 100644 os/io/src/mac.c create mode 100644 os/io/src/mii.c create mode 100644 os/io/src/mmc_spi.c create mode 100644 os/io/src/pal.c create mode 100644 os/io/src/serial.c create mode 100644 os/io/src/spi.c (limited to 'os') diff --git a/os/io/adc.c b/os/io/adc.c deleted file mode 100644 index af4508ab7..000000000 --- a/os/io/adc.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/** - * @brief ADC Driver initialization. - */ -void adcInit(void) { - - adc_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p ADCDriver structure. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -void adcObjectInit(ADCDriver *adcp) { - - adcp->ad_state = ADC_STOP; - adcp->ad_config = NULL; - adcp->ad_callback = NULL; - adcp->ad_samples = NULL; - adcp->ad_depth = 0; - adcp->ad_grpp = NULL; - chSemInit(&adcp->ad_sem, 0); -} - -/** - * @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 - */ -void adcStart(ADCDriver *adcp, const ADCConfig *config) { - - chDbgCheck((adcp != NULL) && (config != NULL), "adcStart"); - - chSysLock(); - chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY), - "adcStart(), #1", - "invalid state"); - adcp->ad_config = config; - adc_lld_start(adcp); - adcp->ad_state = ADC_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the ADC peripheral. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -void adcStop(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcStop"); - - chSysLock(); - chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY), - "adcStop(), #1", - "invalid state"); - adc_lld_stop(adcp); - adcp->ad_state = ADC_STOP; - chSysUnlock(); -} - -/** - * @brief Starts an ADC conversion. - * @details Starts a conversion operation, there are two kind of conversion - * modes: - * - LINEAR, this mode is activated when the @p callback - * parameter is set to @p NULL, in this mode the buffer is filled - * once and then the conversion stops automatically. - * - CIRCULAR, when a callback function is defined the - * conversion never stops and the buffer is filled circularly. - * During the conversion the callback function is invoked when - * the buffer is 50% filled and when the buffer is 100% filled, - * this way is possible to process the conversion stream in real - * time. This kind of conversion can only be stopped by explicitly - * invoking @p adcStopConversion(). - * . - * - * @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. - * @param[in] callback pointer to the conversion callback function - * @return The operation status. - * @retval FALSE the conversion has been started. - * @retval TRUE the driver is busy, conversion not started. - * - * @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. - */ -bool_t adcStartConversion(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth, - adccallback_t callback) { - - chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && - ((depth == 1) || ((depth & 1) == 0)), - "adcStartConversion"); - - chSysLock(); - chDbgAssert((adcp->ad_state == ADC_READY) || - (adcp->ad_state == ADC_RUNNING), - "adcStartConversion(), #1", - "invalid state"); - if (adcp->ad_state == ADC_RUNNING) { - chSysUnlock(); - return TRUE; - } - adcp->ad_callback = callback; - adcp->ad_samples = samples; - adcp->ad_depth = depth; - adcp->ad_grpp = grpp; - adc_lld_start_conversion(adcp); - adcp->ad_state = ADC_RUNNING; - chSysUnlock(); - return FALSE; -} - -/** - * @brief Stops an ongoing conversion. - * - * @param[in] adcp pointer to the @p ADCDriver object - */ -void adcStopConversion(ADCDriver *adcp) { - - chDbgCheck(adcp != NULL, "adcStopConversion"); - - chSysLock(); - chDbgAssert((adcp->ad_state == ADC_READY) || - (adcp->ad_state == ADC_RUNNING), - "adcStopConversion(), #1", - "invalid state"); - if (adcp->ad_state == ADC_RUNNING) { - adc_lld_stop_conversion(adcp); - adcp->ad_grpp = NULL; - adcp->ad_state = ADC_READY; - } - chSysUnlock(); -} - -/** - * @brief Waits for completion. - * - * @param[in] adcp pointer to the @p ADCDriver object - * @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 conversion finished (or not started). - * @retval RDY_TIMEOUT conversion not finished within the specified time. - */ -msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout) { - - chSysLock(); - chDbgAssert((adcp->ad_state == ADC_READY) || - (adcp->ad_state == ADC_RUNNING), - "adcWaitConversion(), #1", - "invalid state"); - if (adcp->ad_state == ADC_RUNNING) { - if (chSemWaitTimeoutS(&adcp->ad_sem, timeout) == RDY_TIMEOUT) { - chSysUnlock(); - return RDY_TIMEOUT; - } - } - chSysUnlock(); - return RDY_OK; -} - -/** @} */ diff --git a/os/io/adc.h b/os/io/adc.h deleted file mode 100644 index 08e83caa2..000000000 --- a/os/io/adc.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief ADC Driver macros and structures. - * @addtogroup ADC - * @{ - */ - -#ifndef _ADC_H_ -#define _ADC_H_ - -#if !CH_USE_SEMAPHORES -#error "ADC driver requires CH_USE_SEMAPHORES" -#endif - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - ADC_UNINIT = 0, /**< @brief Not initialized. */ - ADC_STOP = 1, /**< @brief Stopped. */ - ADC_READY = 2, /**< @brief Ready. */ - ADC_RUNNING = 3 /**< @brief Conversion running. */ -} adcstate_t; - -#include "adc_lld.h" - -#ifdef __cplusplus -extern "C" { -#endif - void adcInit(void); - void adcObjectInit(ADCDriver *adcp); - void adcStart(ADCDriver *adcp, const ADCConfig *config); - void adcStop(ADCDriver *adcp); - bool_t adcStartConversion(ADCDriver *adcp, - const ADCConversionGroup *grpp, - adcsample_t *samples, - size_t depth, - adccallback_t callback); - void adcStopConversion(ADCDriver *adcp); - msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout); -#ifdef __cplusplus -} -#endif - -#endif /* _ADC_H_ */ - -/** @} */ diff --git a/os/io/can.c b/os/io/can.c deleted file mode 100644 index 4c88f9c71..000000000 --- a/os/io/can.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/** - * @brief CAN Driver initialization. - */ -void canInit(void) { - - can_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p CANDriver structure. - * - * @param[in] canp pointer to the @p CANDriver object - */ -void canObjectInit(CANDriver *canp) { - - canp->can_state = CAN_STOP; - canp->can_config = NULL; - chSemInit(&canp->can_txsem); - chSemInit(&canp->can_rxsem); - chEvtInit(&canp->can_rxfull_event); - chEvtInit(&canp->can_txempty_event); -#if CAN_USE_SLEEP_MODE - chEvtInit(&canp->can_sleep_event); - chEvtInit(&canp->can_wakeup_event); -#endif /* CAN_USE_SLEEP_MODE */ -} - -/** - * @brief Configures and activates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - * @param[in] config pointer to the @p CANConfig object - */ -void canStart(CANDriver *canp, const CANConfig *config) { - - chDbgCheck((canp != NULL) && (config != NULL), "canStart"); - - chSysLock(); - chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), - "canStart(), #1", - "invalid state"); - canp->can_config = config; - can_lld_start(canp); - canp->can_state = CAN_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the CAN peripheral. - * - * @param[in] canp pointer to the @p CANDriver object - */ -void canStop(CANDriver *canp) { - - chDbgCheck(canp != NULL, "canStop"); - - chSysLock(); - chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), - "canStop(), #1", - "invalid state"); - can_lld_stop(canp); - canp->can_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] cfp 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 operation not finished within the specified time. - * @retval RDY_RESET driver stopped while waiting. - */ -msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) { - msg_t msg; - - chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit"); - - chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), - "canTransmit(), #1", - "invalid state"); - if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { - msg = chSemWaitTimeoutS(&canp->can_txsem, timeout); - if (msg != RDY_OK) { - chSysUnlock(); - return msg; - } - } - msg = can_lld_transmit(canp, cfp); - chSysUnlock(); - return msg; -} - -/** - * @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[out] cfp 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. - * - @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 operation not finished within the specified time. - * @retval RDY_RESET driver stopped while waiting. - */ -msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { - msg_t msg; - - chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive"); - - chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), - "canReceive(), #1", - "invalid state"); - if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { - msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout); - if (msg != RDY_OK) { - chSysUnlock(); - return msg; - } - } - msg = can_lld_receive(canp, cfp); - chSysUnlock(); - return msg; -} - -#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) -/** - * @brief Enters the sleep mode. - * - * @param[in] canp pointer to the @p CANDriver object - */ -void canSleep(CANDriver *canp) { - - chDbgCheck(canp != NULL, "canSleep"); - - chSysLock(); - chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), - "canSleep(), #1", - "invalid state"); - if (canp->can_state = CAN_READY) { - can_lld_sleep(canp); - canp->can_state = CAN_SLEEP; - chEvtBroadcastI(&canp->can_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->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), - "canWakeup(), #1", - "invalid state"); - if (canp->can_state = CAN_SLEEP) { - can_lld_wakeup(canp); - canp->can_state = CAN_READY; - chEvtBroadcastI(&canp->can_wakeup_event); - chSchRescheduleS(); - } - chSysUnlock(); -} -#endif /* CAN_USE_SLEEP_MODE */ - -/** @} */ diff --git a/os/io/can.h b/os/io/can.h deleted file mode 100644 index 9d9462f86..000000000 --- a/os/io/can.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief CAN Driver macros and structures. - * @addtogroup CAN - * @{ - */ - -#ifndef _CAN_H_ -#define _CAN_H_ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - CAN_UNINIT = 0, /**< @brief Not initialized. */ - CAN_STOP = 1, /**< @brief Stopped. */ - CAN_READY = 2, /**< @brief Ready. */ - CAN_SLEEP = 3 /**< @brief Sleep state. */ -} canstate_t; - -#include "can_lld.h" - -#ifdef __cplusplus -extern "C" { -#endif - void canInit(void); - void canObjectInit(CANDriver *canp); - void canStart(CANDriver *canp, const CANConfig *config); - void canStop(CANDriver *canp); - msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout); - msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout); -#if CAN_USE_SLEEP_MODE - void canSleep(CANDriver *canp); - void canWakeup(CANDriver *canp); -#endif /* CAN_USE_SLEEP_MODE */ -#ifdef __cplusplus -} -#endif - -#endif /* _CAN_H_ */ - -/** @} */ diff --git a/os/io/include/adc.h b/os/io/include/adc.h new file mode 100644 index 000000000..08e83caa2 --- /dev/null +++ b/os/io/include/adc.h @@ -0,0 +1,66 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief ADC Driver macros and structures. + * @addtogroup ADC + * @{ + */ + +#ifndef _ADC_H_ +#define _ADC_H_ + +#if !CH_USE_SEMAPHORES +#error "ADC driver requires CH_USE_SEMAPHORES" +#endif + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + ADC_UNINIT = 0, /**< @brief Not initialized. */ + ADC_STOP = 1, /**< @brief Stopped. */ + ADC_READY = 2, /**< @brief Ready. */ + ADC_RUNNING = 3 /**< @brief Conversion running. */ +} adcstate_t; + +#include "adc_lld.h" + +#ifdef __cplusplus +extern "C" { +#endif + void adcInit(void); + void adcObjectInit(ADCDriver *adcp); + void adcStart(ADCDriver *adcp, const ADCConfig *config); + void adcStop(ADCDriver *adcp); + bool_t adcStartConversion(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth, + adccallback_t callback); + void adcStopConversion(ADCDriver *adcp); + msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout); +#ifdef __cplusplus +} +#endif + +#endif /* _ADC_H_ */ + +/** @} */ diff --git a/os/io/include/can.h b/os/io/include/can.h new file mode 100644 index 000000000..9d9462f86 --- /dev/null +++ b/os/io/include/can.h @@ -0,0 +1,61 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief CAN Driver macros and structures. + * @addtogroup CAN + * @{ + */ + +#ifndef _CAN_H_ +#define _CAN_H_ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + CAN_UNINIT = 0, /**< @brief Not initialized. */ + CAN_STOP = 1, /**< @brief Stopped. */ + CAN_READY = 2, /**< @brief Ready. */ + CAN_SLEEP = 3 /**< @brief Sleep state. */ +} canstate_t; + +#include "can_lld.h" + +#ifdef __cplusplus +extern "C" { +#endif + void canInit(void); + void canObjectInit(CANDriver *canp); + void canStart(CANDriver *canp, const CANConfig *config); + void canStop(CANDriver *canp); + msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout); + msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout); +#if CAN_USE_SLEEP_MODE + void canSleep(CANDriver *canp); + void canWakeup(CANDriver *canp); +#endif /* CAN_USE_SLEEP_MODE */ +#ifdef __cplusplus +} +#endif + +#endif /* _CAN_H_ */ + +/** @} */ diff --git a/os/io/include/mac.h b/os/io/include/mac.h new file mode 100644 index 000000000..9a83cc2b8 --- /dev/null +++ b/os/io/include/mac.h @@ -0,0 +1,89 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief MAC Driver macros and structures. + * @addtogroup MAC + * @{ + */ + +#ifndef _MAC_H_ +#define _MAC_H_ + +#include "mac_lld.h" + +/** + * @brief Returns the received frames event source. + * + * @param[in] macp pointer to the @p MACDriver object + * @return The pointer to the @p EventSource structure. + */ +#if CH_USE_EVENTS || defined(__DOXYGEN__) +#define macGetReceiveEventSource(macp) (&(macp)->md_rdevent) +#endif + +/** + * @brief Writes to a transmit descriptor's stream. + * + * @param[in] tdp pointer to a @p MACTransmitDescriptor structure + * @param[in] buf pointer to the buffer containing the data to be written + * @param[in] size number of bytes to be written + * @return The number of bytes written into the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if the maximum frame size is reached. + */ +#define macWriteTransmitDescriptor(tdp, buf, size) \ + mac_lld_write_transmit_descriptor(tdp, buf, size) + +/** + * @brief Reads from a receive descriptor's stream. + * + * @param[in] rdp pointer to a @p MACReceiveDescriptor structure + * @param[in] buf pointer to the buffer that will receive the read data + * @param[in] size number of bytes to be read + * @return The number of bytes read from the descriptor's stream, this + * value can be less than the amount specified in the parameter + * @p size if there are no more bytes to read. + */ +#define macReadReceiveDescriptor(rdp, buf, size) \ + mac_lld_read_receive_descriptor(rdp, buf, size) + +#ifdef __cplusplus +extern "C" { +#endif + void macInit(void); + void macObjectInit(MACDriver *macp); + void macSetAddress(MACDriver *macp, const uint8_t *p); + msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time); + void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); + msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time); + void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); + bool_t macPollLinkStatus(MACDriver *macp); +#ifdef __cplusplus +} +#endif + +#endif /* _MAC_H_ */ + +/** @} */ diff --git a/os/io/include/mii.h b/os/io/include/mii.h new file mode 100644 index 000000000..a236c6dc3 --- /dev/null +++ b/os/io/include/mii.h @@ -0,0 +1,220 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 are borrowed by the Linux include file linux/mii.h: + * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) + */ + +/** + * @file mii.h + * @brief MII Driver macros and structures. + * @addtogroup MII + * @{ + */ + +#ifndef _MII_H_ +#define _MII_H_ + +#include "mac_lld.h" +#include "mii_lld.h" + +/* + * Generic MII registers. Note, not all registers are present on all PHY + * devices and some extra registers may be present. + */ +#define MII_BMCR 0x00 /**< Basic mode control register. */ +#define MII_BMSR 0x01 /**< Basic mode status register. */ +#define MII_PHYSID1 0x02 /**< PHYS ID 1. */ +#define MII_PHYSID2 0x03 /**< PHYS ID 2. */ +#define MII_ADVERTISE 0x04 /**< Advertisement control reg. */ +#define MII_LPA 0x05 /**< Link partner ability reg. */ +#define MII_EXPANSION 0x06 /**< Expansion register. */ +#define MII_CTRL1000 0x09 /**< 1000BASE-T control. */ +#define MII_STAT1000 0x0a /**< 1000BASE-T status. */ +#define MII_ESTATUS 0x0f /**< Extended Status. */ +#define MII_DCOUNTER 0x12 /**< Disconnect counter. */ +#define MII_FCSCOUNTER 0x13 /**< False carrier counter. */ +#define MII_NWAYTEST 0x14 /**< N-way auto-neg test reg. */ +#define MII_RERRCOUNTER 0x15 /**< Receive error counter. */ +#define MII_SREVISION 0x16 /**< Silicon revision. */ +#define MII_RESV1 0x17 /**< Reserved. */ +#define MII_LBRERROR 0x18 /**< Lpback, rx, bypass error. */ +#define MII_PHYADDR 0x19 /**< PHY address. */ +#define MII_RESV2 0x1a /**< Reserved. */ +#define MII_TPISTATUS 0x1b /**< TPI status for 10mbps. */ +#define MII_NCONFIG 0x1c /**< Network interface config. */ + +/* + * Basic mode control register. + */ +#define BMCR_RESV 0x003f /**< Unused. */ +#define BMCR_SPEED1000 0x0040 /**< MSB of Speed (1000). */ +#define BMCR_CTST 0x0080 /**< Collision test. */ +#define BMCR_FULLDPLX 0x0100 /**< Full duplex. */ +#define BMCR_ANRESTART 0x0200 /**< Auto negotiation restart. */ +#define BMCR_ISOLATE 0x0400 /**< Disconnect DP83840 from MII. */ +#define BMCR_PDOWN 0x0800 /**< Powerdown. */ +#define BMCR_ANENABLE 0x1000 /**< Enable auto negotiation. */ +#define BMCR_SPEED100 0x2000 /**< Select 100Mbps. */ +#define BMCR_LOOPBACK 0x4000 /**< TXD loopback bits. */ +#define BMCR_RESET 0x8000 /**< Reset. */ + +/* + * Basic mode status register. + */ +#define BMSR_ERCAP 0x0001 /**< Ext-reg capability. */ +#define BMSR_JCD 0x0002 /**< Jabber detected. */ +#define BMSR_LSTATUS 0x0004 /**< Link status. */ +#define BMSR_ANEGCAPABLE 0x0008 /**< Able to do auto-negotiation. */ +#define BMSR_RFAULT 0x0010 /**< Remote fault detected. */ +#define BMSR_ANEGCOMPLETE 0x0020 /**< Auto-negotiation complete. */ +#define BMSR_RESV 0x00c0 /**< Unused. */ +#define BMSR_ESTATEN 0x0100 /**< Extended Status in R15. */ +#define BMSR_100HALF2 0x0200 /**< Can do 100BASE-T2 HDX. */ +#define BMSR_100FULL2 0x0400 /**< Can do 100BASE-T2 FDX. */ +#define BMSR_10HALF 0x0800 /**< Can do 10mbps, half-duplex. */ +#define BMSR_10FULL 0x1000 /**< Can do 10mbps, full-duplex. */ +#define BMSR_100HALF 0x2000 /**< Can do 100mbps, half-duplex. */ +#define BMSR_100FULL 0x4000 /**< Can do 100mbps, full-duplex. */ +#define BMSR_100BASE4 0x8000 /**< Can do 100mbps, 4k packets. */ + +/* + * Advertisement control register. + */ +#define ADVERTISE_SLCT 0x001f /**< Selector bits. */ +#define ADVERTISE_CSMA 0x0001 /**< Only selector supported. */ +#define ADVERTISE_10HALF 0x0020 /**< Try for 10mbps half-duplex. */ +#define ADVERTISE_1000XFULL 0x0020 /**< Try for 1000BASE-X full-duplex.*/ +#define ADVERTISE_10FULL 0x0040 /**< Try for 10mbps full-duplex. */ +#define ADVERTISE_1000XHALF 0x0040 /**< Try for 1000BASE-X half-duplex.*/ +#define ADVERTISE_100HALF 0x0080 /**< Try for 100mbps half-duplex. */ +#define ADVERTISE_1000XPAUSE 0x0080 /**< Try for 1000BASE-X pause. */ +#define ADVERTISE_100FULL 0x0100 /**< Try for 100mbps full-duplex. */ +#define ADVERTISE_1000XPSE_ASYM 0x0100 /**< Try for 1000BASE-X asym pause. */ +#define ADVERTISE_100BASE4 0x0200 /**< Try for 100mbps 4k packets. */ +#define ADVERTISE_PAUSE_CAP 0x0400 /**< Try for pause. */ +#define ADVERTISE_PAUSE_ASYM 0x0800 /**< Try for asymetric pause. */ +#define ADVERTISE_RESV 0x1000 /**< Unused. */ +#define ADVERTISE_RFAULT 0x2000 /**< Say we can detect faults. */ +#define ADVERTISE_LPACK 0x4000 /**< Ack link partners response. */ +#define ADVERTISE_NPAGE 0x8000 /**< Next page bit. */ + +#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ + ADVERTISE_CSMA) +#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ + ADVERTISE_100HALF | ADVERTISE_100FULL) + +/* + * Link partner ability register. + */ +#define LPA_SLCT 0x001f /**< Same as advertise selector. */ +#define LPA_10HALF 0x0020 /**< Can do 10mbps half-duplex. */ +#define LPA_1000XFULL 0x0020 /**< Can do 1000BASE-X full-duplex. */ +#define LPA_10FULL 0x0040 /**< Can do 10mbps full-duplex. */ +#define LPA_1000XHALF 0x0040 /**< Can do 1000BASE-X half-duplex. */ +#define LPA_100HALF 0x0080 /**< Can do 100mbps half-duplex. */ +#define LPA_1000XPAUSE 0x0080 /**< Can do 1000BASE-X pause. */ +#define LPA_100FULL 0x0100 /**< Can do 100mbps full-duplex. */ +#define LPA_1000XPAUSE_ASYM 0x0100 /**< Can do 1000BASE-X pause asym. */ +#define LPA_100BASE4 0x0200 /**< Can do 100mbps 4k packets. */ +#define LPA_PAUSE_CAP 0x0400 /**< Can pause. */ +#define LPA_PAUSE_ASYM 0x0800 /**< Can pause asymetrically. */ +#define LPA_RESV 0x1000 /**< Unused. */ +#define LPA_RFAULT 0x2000 /**< Link partner faulted. */ +#define LPA_LPACK 0x4000 /**< Link partner acked us. */ +#define LPA_NPAGE 0x8000 /**< Next page bit. */ + +#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) +#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) + +/* + * Expansion register for auto-negotiation. + */ +#define EXPANSION_NWAY 0x0001 /**< Can do N-way auto-nego. */ +#define EXPANSION_LCWP 0x0002 /**< Got new RX page code word. */ +#define EXPANSION_ENABLENPAGE 0x0004 /**< This enables npage words. */ +#define EXPANSION_NPCAPABLE 0x0008 /**< Link partner supports npage. */ +#define EXPANSION_MFAULTS 0x0010 /**< Multiple faults detected. */ +#define EXPANSION_RESV 0xffe0 /**< Unused. */ + +#define ESTATUS_1000_TFULL 0x2000 /**< Can do 1000BT Full. */ +#define ESTATUS_1000_THALF 0x1000 /**< Can do 1000BT Half. */ + +/* + * N-way test register. + */ +#define NWAYTEST_RESV1 0x00ff /**< Unused. */ +#define NWAYTEST_LOOPBACK 0x0100 /**< Enable loopback for N-way. */ +#define NWAYTEST_RESV2 0xfe00 /**< Unused. */ + +/* + * 1000BASE-T Control register. + */ +#define ADVERTISE_1000FULL 0x0200 /**< Advertise 1000BASE-T full duplex.*/ +#define ADVERTISE_1000HALF 0x0100 /**< Advertise 1000BASE-T half duplex.*/ + +/* + * 1000BASE-T Status register. + */ +#define LPA_1000LOCALRXOK 0x2000 /**< Link partner local receiver status.*/ +#define LPA_1000REMRXOK 0x1000 /**< Link partner remote receiver status.*/ +#define LPA_1000FULL 0x0800 /**< Link partner 1000BASE-T full duplex.*/ +#define LPA_1000HALF 0x0400 /**< Link partner 1000BASE-T half duplex.*/ + +/* + * PHY identifiers. + */ +#define MII_DM9161_ID 0x0181b8a0 +#define MII_AM79C875_ID 0x00225540 +#define MII_KS8721_ID 0x00221610 + +/** + * @brief MII Driver initialization. + */ +#define miiInit() mii_lld_init() + +/** + * Resets a MII device. + * + * @param[in] macp pointer to the @p MACDriver object + */ +#define miiReset(macp) mii_lld_reset(macp) + +/** + * @brief Reads a MII register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param addr the register address + * @return The register value. + */ +#define miiGet(macp, addr) mii_lld_get(macp, addr) + +/** + * @brief Writes a MII register. + * + * @param[in] macp pointer to the @p MACDriver object + * @param addr the register address + * @param value the new register value + */ +#define miiPut(macp, addr, value) mii_lld_put(macp, addr, value) + +#endif /**< _MII_H_ */ + +/** @} */ diff --git a/os/io/include/mmc_spi.h b/os/io/include/mmc_spi.h new file mode 100644 index 000000000..96e5e3ec5 --- /dev/null +++ b/os/io/include/mmc_spi.h @@ -0,0 +1,204 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 mmc_spi.h + * @brief MMC over SPI driver header + * @addtogroup MMC_SPI + * @{ + */ + +#ifndef _MMC_SPI_H_ +#define _MMC_SPI_H_ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Block size for MMC transfers. + */ +#if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__) +#define MMC_SECTOR_SIZE 512 +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/** + * @brief Number of positive insertion queries before generating the + * insertion event. + */ +#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__) +#define MMC_POLLING_INTERVAL 10 +#endif + +/** + * @brief Interval, in milliseconds, between insertion queries. + */ +#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__) +#define MMC_POLLING_DELAY 10 +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +#define MMC_CMD0_RETRY 10 +#define MMC_CMD1_RETRY 100 +#define MMC_WAIT_DATA 10000 + +#define MMC_CMDGOIDLE 0 +#define MMC_CMDINIT 1 +#define MMC_CMDREADCSD 9 +#define MMC_CMDSTOP 12 +#define MMC_CMDSETBLOCKLEN 16 +#define MMC_CMDREAD 17 +#define MMC_CMDREADMULTIPLE 18 +#define MMC_CMDWRITE 24 +#define MMC_CMDWRITEMULTIPLE 25 + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + MMC_UNINIT = 0, /**< @brief Not initialized. */ + MMC_STOP = 1, /**< @brief Stopped. */ + MMC_WAIT = 2, /**< @brief Waiting card. */ + MMC_INSERTED = 3, /**< @brief Card inserted. */ + MMC_READY = 4, /**< @brief Card ready. */ + MMC_READING = 5, /**< @brief Reading. */ + MMC_WRITING = 6 /**< @brief Writing. */ +} mmcstate_t; + +/** + * @brief Function used to query some hardware status bits. + * + * @return The status. + */ +typedef bool_t (*mmcquery_t)(void); + +/** + * @brief Driver configuration structure. + */ +typedef struct { + +} MMCConfig; + +/** + * @brief Structure representing a MMC driver. + */ +typedef struct { + /** + * @brief Driver state. + */ + mmcstate_t mmc_state; + /** + * @brief Current configuration data. + */ + const MMCConfig *mmc_config; + /** + * @brief SPI driver associated to this MMC driver. + */ + SPIDriver *mmc_spip; + /** + * @brief SPI low speed configuration used during initialization. + */ + const SPIConfig *mmc_lscfg; + /** + * @brief SPI high speed configuration used during transfers. + */ + const SPIConfig *mmc_hscfg; + /** + * @brief Write protect status query function. + */ + mmcquery_t mmc_is_protected; + /** + * @brief Insertion status query function. + */ + mmcquery_t mmc_is_inserted; + /** + * @brief Card insertion event source. + */ + EventSource mmc_inserted_event; + /** + * @brief Card removal event source. + */ + EventSource mmc_removed_event; + /** + * @brief MMC insertion polling timer. + */ + VirtualTimer mmc_vt; + /** + * @brief Insertion counter. + */ + uint_fast8_t mmc_cnt; +} MMCDriver; + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +/** + * @brief Returns the driver state. + */ +#define mmcGetDriverState(mmcp) ((mmcp)->mmc_state) + +/** + * @brief Returns the write protect status. + */ +#define mmcIsWriteProtected(mmcp) ((mmcp)->mmc_is_protected()) + +#ifdef __cplusplus +extern "C" { +#endif + void mmcInit(void); + void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip, + const SPIConfig *lscfg, const SPIConfig *hscfg, + mmcquery_t is_protected, mmcquery_t is_inserted); + void mmcStart(MMCDriver *mmcp, const MMCConfig *config); + void mmcStop(MMCDriver *mmcp); + bool_t mmcConnect(MMCDriver *mmcp); + bool_t mmcDisconnect(MMCDriver *mmcp); + bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); + bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); + bool_t mmcStopSequentialRead(MMCDriver *mmcp); + bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk); + bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer); + bool_t mmcStopSequentialWrite(MMCDriver *mmcp); +#ifdef __cplusplus +} +#endif + +#endif /* _MMC_SPI_H_ */ + +/** @} */ diff --git a/os/io/include/pal.h b/os/io/include/pal.h new file mode 100644 index 000000000..67bc424b1 --- /dev/null +++ b/os/io/include/pal.h @@ -0,0 +1,467 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief I/O Ports Abstraction Layer macros, types and structures + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_H_ +#define _PAL_H_ + +/** + * @brief Bits in a mode word dedicated as mode selector. + * @details The other bits are not defined and may be used as device-specific + * option bits. + */ +#define PAL_MODE_MASK 0xF + +/** + * @brief After reset state. + * @details The state itself is not specified and is architecture dependent, + * it is guaranteed to be equal to the after-reset state. It is + * usually an input state. + */ +#define PAL_MODE_RESET 0 + +/** + * @brief Safe state for unconnected pads. + * @details The state itself is not specified and is architecture dependent, + * it may be mapped on @p PAL_MODE_INPUT_PULLUP, + * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL as + * example. + */ +#define PAL_MODE_UNCONNECTED 1 + +/** + * @brief Regular input high-Z pad. + */ +#define PAL_MODE_INPUT 2 + +/** + * @brief Input pad with weak pull up resistor. + */ +#define PAL_MODE_INPUT_PULLUP 3 + +/** + * @brief Input pad with weak pull down resistor. + */ +#define PAL_MODE_INPUT_PULLDOWN 4 + +/** + * @brief Analog input mode. + */ +#define PAL_MODE_INPUT_ANALOG 5 + +/** + * @brief Push-pull output pad. + */ +#define PAL_MODE_OUTPUT_PUSHPULL 6 + +/** + * @brief Open-drain output pad. + */ +#define PAL_MODE_OUTPUT_OPENDRAIN 7 + +#ifndef _PAL_LLD_H_ +#include "pal_lld.h" +#endif + +/** + * @brief Logical low state. + */ +#define PAL_LOW 0 + +/** + * @brief Logical high state. + */ +#define PAL_HIGH 1 + +/** + * @brief Port bit helper macro. + * @details This macro calculates the mask of a bit within a port. + * + * @param[in] n the bit position within the port + * @return The bit mask. + */ +#define PAL_PORT_BIT(n) ((ioportmask_t)(1 << (n))) + + +/** + * @brief Bits group mask helper. + * @details This macro calculates the mask of a bits group. + * + * @param[in] width the group width + * @return The group mask. + */ +#define PAL_GROUP_MASK(width) ((ioportmask_t)(1 << (width)) - 1) + +/** + * @brief Data part of a static I/O bus initializer. + * @details This macro should be used when statically initializing an I/O bus + * that is part of a bigger structure. + * + * @param name the name of the IOBus variable + * @param port the I/O port descriptor + * @param width the bus width in bits + * @param offset the bus bit offset within the port + */ +#define _IOBUS_DATA(name, port, width, offset) \ + {port, PAL_GROUP_MASK(width), offset} + +/** + * @brief Static I/O bus initializer. + * + * @param name the name of the IOBus variable + * @param port the I/O port descriptor + * @param width the bus width in bits + * @param offset the bus bit offset within the port + */ +#define IOBUS_DECL(name, port, width, offset) \ + IOBus name = _IOBUS_DATA(name, port, width, offset) + +/** + * @brief I/O bus descriptor. + * @details This structure describes a group of contiguous digital I/O lines + * that have to be handled as bus. + * @note I/O operations on a bus do not affect I/O lines on the same port but + * not belonging to the bus. + */ +typedef struct { + /** Port identifier.*/ + ioportid_t bus_portid; + /** Bus mask aligned to port bit 0. The bus mask implicitly define the bus + width. A logical AND is performed on the bus data.*/ + ioportmask_t bus_mask; + /** Offset, within the port, of the least significant bit of the bus.*/ + uint_fast8_t bus_offset; +} IOBus; + +/** + * @brief PAL subsystem initialization. + * + * @param[in] config pointer to an architecture specific configuration + * structure. This structure is defined in the low level driver + * header. + */ +#define palInit(config) pal_lld_init(config) + +/** + * @brief Reads the physical I/O port states. + * + * @param[in] port the port identifier + * @return The port logical states. + * + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + */ +#if !defined(pal_lld_readport) || defined(__DOXYGEN__) +#define palReadPort(port) ((void)(port), 0) +#else +#define palReadPort(port) pal_lld_readport(port) +#endif + +/** + * @brief Reads the output latch. + * @details The purpose of this function is to read back the latched output + * value. + * + * @param[in] port the port identifier + * @return The latched logical states. + * + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + */ +#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__) +#define palReadLatch(port) ((void)(port), 0) +#else +#define palReadLatch(port) pal_lld_readlatch(port) +#endif + +/** + * @brief Writes a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be written on the specified port + * + * @note The default implementation does nothing except computing the + * parameters eventual side effects. + */ +#if !defined(pal_lld_writeport) || defined(__DOXYGEN__) +#define palWritePort(port, bits) ((void)(port), (void)(bits)) +#else +#define palWritePort(port, bits) pal_lld_writeport(port, bits) +#endif + +/** + * @brief Sets a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be ORed on the specified port + * + * @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. + */ +#if !defined(pal_lld_setport) || defined(__DOXYGEN__) +#define palSetPort(port, bits) { \ + palWritePort(port, palReadLatch(port) | (bits)); \ +} +#else +#define palSetPort(port, bits) pal_lld_setport(port, bits) +#endif + +/** + * @brief Clears a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be cleared on the specified port + * + * @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. + */ +#if !defined(pal_lld_clearport) || defined(__DOXYGEN__) +#define palClearPort(port, bits) { \ + palWritePort(port, palReadLatch(port) & ~(bits)); \ +} +#else +#define palClearPort(port, bits) pal_lld_clearport(port, bits) +#endif + +/** + * @brief Toggles a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be XORed on the specified port + * + * @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. + */ +#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__) +#define palTogglePort(port, bits) { \ + palWritePort(port, palReadLatch(port) ^ (bits)); \ +} +#else +#define palTogglePort(port, bits) pal_lld_toggleport(port, bits) +#endif + +/** + * @brief Reads a group of bits. + * + * @param[in] port the port identifier + * @param[in] mask the group mask, a logical AND is performed on the input + * data + * @param[in] offset the group bit offset within the port + * @return The group logical states. + */ +#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__) +#define palReadGroup(port, mask, offset) \ + ((palReadPort(port) >> (offset)) & (mask)) +#else +#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset) +#endif + +/** + * @brief Writes a group of bits. + * + * @param[in] port the port identifier + * @param[in] mask the group mask, a logical AND is performed on the output + * data + * @param[in] offset the group bit offset within the port + * @param[in] bits the bits to be written. Values exceeding the group width + * are masked. + */ +#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__) +#define palWriteGroup(port, mask, offset, bits) { \ + palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \ + (((bits) & (mask)) << (offset))); \ +} +#else +#define palWriteGroup(port, mask, offset, bits) \ + pal_lld_writegroup(port, mask, offset, bits) +#endif + + +/** + * @brief Pads group mode setup. + * @details This function programs a pads group belonging to the same port + * with the specified mode. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] mode the setup mode + * + * @note Programming an unknown or unsupported mode is silently ignored. + */ +#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__) +#define palSetGroupMode(port, mask, mode) +#else +#define palSetGroupMode(port, mask, mode) pal_lld_setgroupmode(port, mask, mode) +#endif + +/** + * @brief Reads an input pad logical state. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @return The logical state. + * @retval 0 low logical state. + * @retval 1 high logical state. + * + * @note The default implementation not necessarily optimal. Low level drivers + * may optimize the function by using specific hardware or coding. + * @note The default implementation internally uses the @p palReadPort(). + */ +#if !defined(pal_lld_readpad) || defined(__DOXYGEN__) +#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1) +#else +#define palReadPad(port, pad) pal_lld_readpad(port, pad) +#endif + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @param[out] bit the logical value, the value must be @p 0 or @p 1 + * + * @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. + * @note The default implementation internally uses the @p palReadLatch() and + * @p palWritePort(). + */ +#if !defined(pal_lld_writepad) || defined(__DOXYGEN__) +#define palWritePad(port, pad, bit) { \ + palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \ + (((bit) & 1) << pad)); \ +} +#else +#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit) +#endif + +/** + * @brief Sets a pad logical state to @p 1. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @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. + * @note The default implementation internally uses the @p palSetPort(). + */ +#if !defined(pal_lld_setpad) || defined(__DOXYGEN__) +#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad)) +#else +#define palSetPad(port, pad) pal_lld_setpad(port, pad) +#endif + +/** + * @brief Clears a pad logical state to @p 0. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @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. + * @note The default implementation internally uses the @p palClearPort(). + */ +#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__) +#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad)) +#else +#define palClearPad(port, pad) pal_lld_clearpad(port, pad) +#endif + +/** + * @brief Toggles a pad logical state. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @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. + * @note The default implementation internally uses the @p palTogglePort(). + */ +#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__) +#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad)) +#else +#define palTogglePad(port, pad) pal_lld_togglepad(port, pad) +#endif + + +/** + * @brief Pad mode setup. + * @details This function programs a pad with the specified mode. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @param[in] mode the setup mode + * + * @note The default implementation not necessarily optimal. Low level drivers + * may optimize the function by using specific hardware or coding. + * @note Programming an unknown or unsupported mode is silently ignored. + */ +#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__) +#define palSetPadMode(port, pad, mode) \ + palSetGroupMode(port, PAL_PORT_BIT(pad), mode) +#else +#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + ioportmask_t palReadBus(IOBus *bus); + void palWriteBus(IOBus *bus, ioportmask_t bits); + void palSetBusMode(IOBus *bus, uint_fast8_t mode); +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_H_ */ + +/** @} */ diff --git a/os/io/include/serial.h b/os/io/include/serial.h new file mode 100644 index 000000000..6324a5f5b --- /dev/null +++ b/os/io/include/serial.h @@ -0,0 +1,193 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief Serial Driver macros and structures. + * @addtogroup SERIAL + * @{ + */ + +#ifndef _SERIAL_H_ +#define _SERIAL_H_ + +/** No pending conditions.*/ +#define SD_NO_ERROR 0 +/** Connection happened.*/ +#define SD_CONNECTED 1 +/** Disconnection happened.*/ +#define SD_DISCONNECTED 2 +/** Parity error happened.*/ +#define SD_PARITY_ERROR 4 +/** Framing error happened.*/ +#define SD_FRAMING_ERROR 8 +/** Overflow happened.*/ +#define SD_OVERRUN_ERROR 16 +/** Break detected.*/ +#define SD_BREAK_DETECTED 32 + +/** + * @brief Structure representing a serial driver. + */ +typedef struct _SerialDriver SerialDriver; + +#include "serial_lld.h" + +/** + * @brief @p SerialDriver specific methods. + */ +struct _serial_driver_methods { +}; + +/** + * @brief @p SerialDriver virtual methods table. + */ +struct SerialDriverVMT { + /** + * @p BaseChannel class inherited methods. + */ + struct _base_channel_methods m0; + /** + * @p BaseAsynchronousChannel class inherited methods. + */ + struct _base_asynchronous_channel_methods m1; + /** + * @p SerialDriver specific methods. + */ + struct _serial_driver_methods m2; +}; + +/** + * @extends BaseAsynchronousChannel + * + * @brief Full duplex serial driver class. + * @details This class extends @p BaseAsynchronousChannel by adding physical + * I/O queues. + */ +struct _SerialDriver { + /** + * Virtual Methods Table. + */ + const struct SerialDriverVMT *vmt; + /** + * @p BaseChannel class inherited data. + */ + struct _base_channel_data d0; + /** + * @p BaseAsynchronousChannel class inherited data. + */ + struct _base_asynchronous_channel_data d1; + /** + * @p SerialDriver specific data. + */ + struct _serial_driver_data d2; +}; + +#ifdef __cplusplus +extern "C" { +#endif + void sdInit(void); + void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify); + void sdStart(SerialDriver *sdp, const SerialDriverConfig *config); + void sdStop(SerialDriver *sdp); + void sdIncomingDataI(SerialDriver *sdp, uint8_t b); + msg_t sdRequestDataI(SerialDriver *sdp); + void sdAddFlagsI(SerialDriver *sdp, sdflags_t mask); + sdflags_t sdGetAndClearFlags(SerialDriver *sdp); +#ifdef __cplusplus +} +#endif + +/** + * @brief Direct output check on a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * checks directly the output queue. This is faster but cannot + * be used to check different channels implementations. + * @see chIOPutWouldBlock() + */ +#define sdPutWouldBlock(sdp) chOQIsFull(&(sdp)->d2.oqueue) + +/** + * @brief Direct input check on a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * checks directly the input queue. This is faster but cannot + * be used to check different channels implementations. + * @see chIOGetWouldBlock() + */ +#define sdGetWouldBlock(sdp) chIQIsEmpty(&(sdp)->d2.iqueue) + +/** + * @brief Direct blocking write to a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * writes directly on the output queue. This is faster but cannot + * be used to write to different channels implementations. + * @see chIOPut() + */ +#define sdPut(sdp, b) chOQPut(&(sdp)->d2.oqueue, b) + +/** + * @brief Direct blocking write on a @p SerialDriver with timeout + * specification. + * @details This function bypasses the indirect access to the channel and + * writes directly on the output queue. This is faster but cannot + * be used to write to different channels implementations. + * @see chIOPutTimeout() + */ +#define sdPutTimeout(sdp, b, t) chOQPutTimeout(&(sdp)->d2.iqueue, b, t) + +/** + * @brief Direct blocking read from a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * @see chIOGet() + */ +#define sdGet(sdp) chIQGet(&(sdp)->d2.iqueue) + +/** + * @brief Direct blocking read from a @p SerialDriver with timeout + * specification. + * @details This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * @see chIOGetTimeout() + */ +#define sdGetTimeout(sdp, t) chIQGetTimeout(&(sdp)->d2.iqueue, t) + +/** + * @brief Direct non-blocking write to a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * writes directly to the output queue. This is faster but cannot + * be used to write from different channels implementations. + * @see chIOWrite() + */ +#define sdWrite(sdp, b, n) chOQWrite(&(sdp)->d2.oqueue, b, n) + +/** + * @brief Direct non-blocking read on a @p SerialDriver. + * @details This function bypasses the indirect access to the channel and + * reads directly from the input queue. This is faster but cannot + * be used to read from different channels implementations. + * @see chIORead() + */ +#define sdRead(sdp, b, n) chIQRead(&(sdp)->d2.iqueue, b, n) + +#endif /* _SERIAL_H_ */ + +/** @} */ diff --git a/os/io/include/spi.h b/os/io/include/spi.h new file mode 100644 index 000000000..cebde453f --- /dev/null +++ b/os/io/include/spi.h @@ -0,0 +1,76 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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.h + * @brief SPI Driver macros and structures. + * @addtogroup SPI + * @{ + */ + +#ifndef _SPI_H_ +#define _SPI_H_ + +/** + * @brief Enables the mutual exclusion APIs on the SPI bus. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +#if SPI_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES +#error "SPI_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" +#endif + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + SPI_UNINIT = 0, /**< @brief Not initialized. */ + SPI_STOP = 1, /**< @brief Stopped. */ + SPI_READY = 2, /**< @brief Ready. */ + SPI_ACTIVE = 3 /**< @brief Slave selected. */ +} spistate_t; + +#include "spi_lld.h" + +#ifdef __cplusplus +extern "C" { +#endif + void spiInit(void); + void spiObjectInit(SPIDriver *spip); + void spiStart(SPIDriver *spip, const SPIConfig *config); + void spiStop(SPIDriver *spip); + void spiSelect(SPIDriver *spip); + void spiUnselect(SPIDriver *spip); + void spiIgnore(SPIDriver *spip, size_t n); + void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); + void spiSend(SPIDriver *spip, size_t n, const void *txbuf); + void spiReceive(SPIDriver *spip, size_t n, void *rxbuf); +#if SPI_USE_MUTUAL_EXCLUSION + void spiAcquireBus(SPIDriver *spip); + void spiReleaseBus(SPIDriver *spip); +#endif /* SPI_USE_MUTUAL_EXCLUSION */ +#ifdef __cplusplus +} +#endif + +#endif /* _SPI_H_ */ + +/** @} */ diff --git a/os/io/mac.c b/os/io/mac.c deleted file mode 100644 index 01541682e..000000000 --- a/os/io/mac.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/** - * @brief MAC Driver initialization. - */ -void macInit(void) { - - mac_lld_init(); -} - -/** - * @brief Initialize the standard part of a @p MACDriver structure. - * - * @param[in] macp pointer to the @p MACDriver object - */ -void macObjectInit(MACDriver *macp) { - - chSemInit(&macp->md_tdsem, 0); - chSemInit(&macp->md_rdsem, 0); -#if CH_USE_EVENTS - chEvtInit(&macp->md_rdevent); -#endif -} - -/** - * @brief MAC address setup. - * - * @param[in] macp pointer to the @p MACDriver object - * @param[in] p pointer to a six bytes buffer containing the MAC address. If - * this parameter is set to @p NULL then a system default MAC is - * used. - * - * @note This function must be invoked only with the driver in the stopped - * state. If invoked on an active interface then it is ignored. - */ -void macSetAddress(MACDriver *macp, const uint8_t *p) { - - mac_lld_set_address(macp, p); -} - -/** - * @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. - */ -msg_t macWaitTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp, - systime_t time) { - msg_t msg; - - while (((msg = max_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) && - (time > 0)) { - chSysLock(); - systime_t now = chTimeNow(); - if ((msg = chSemWaitTimeoutS(&macp->md_tdsem, time)) == RDY_TIMEOUT) - 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 - */ -void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { - - 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. - */ -msg_t macWaitReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp, - systime_t time) { - msg_t msg; - - while (((msg = max_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) && - (time > 0)) { - chSysLock(); - systime_t now = chTimeNow(); - if ((msg = chSemWaitTimeoutS(&macp->md_rdsem, time)) == RDY_TIMEOUT) - 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 - */ -void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { - - 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. - */ -bool_t macPollLinkStatus(MACDriver *macp) { - - return mac_lld_poll_link_status(macp); -} - -/** @} */ diff --git a/os/io/mac.h b/os/io/mac.h deleted file mode 100644 index 9a83cc2b8..000000000 --- a/os/io/mac.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief MAC Driver macros and structures. - * @addtogroup MAC - * @{ - */ - -#ifndef _MAC_H_ -#define _MAC_H_ - -#include "mac_lld.h" - -/** - * @brief Returns the received frames event source. - * - * @param[in] macp pointer to the @p MACDriver object - * @return The pointer to the @p EventSource structure. - */ -#if CH_USE_EVENTS || defined(__DOXYGEN__) -#define macGetReceiveEventSource(macp) (&(macp)->md_rdevent) -#endif - -/** - * @brief Writes to a transmit descriptor's stream. - * - * @param[in] tdp pointer to a @p MACTransmitDescriptor structure - * @param[in] buf pointer to the buffer containing the data to be written - * @param[in] size number of bytes to be written - * @return The number of bytes written into the descriptor's stream, this - * value can be less than the amount specified in the parameter - * @p size if the maximum frame size is reached. - */ -#define macWriteTransmitDescriptor(tdp, buf, size) \ - mac_lld_write_transmit_descriptor(tdp, buf, size) - -/** - * @brief Reads from a receive descriptor's stream. - * - * @param[in] rdp pointer to a @p MACReceiveDescriptor structure - * @param[in] buf pointer to the buffer that will receive the read data - * @param[in] size number of bytes to be read - * @return The number of bytes read from the descriptor's stream, this - * value can be less than the amount specified in the parameter - * @p size if there are no more bytes to read. - */ -#define macReadReceiveDescriptor(rdp, buf, size) \ - mac_lld_read_receive_descriptor(rdp, buf, size) - -#ifdef __cplusplus -extern "C" { -#endif - void macInit(void); - void macObjectInit(MACDriver *macp); - void macSetAddress(MACDriver *macp, const uint8_t *p); - msg_t macWaitTransmitDescriptor(MACDriver *macp, - MACTransmitDescriptor *tdp, - systime_t time); - void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp); - msg_t macWaitReceiveDescriptor(MACDriver *macp, - MACReceiveDescriptor *rdp, - systime_t time); - void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp); - bool_t macPollLinkStatus(MACDriver *macp); -#ifdef __cplusplus -} -#endif - -#endif /* _MAC_H_ */ - -/** @} */ diff --git a/os/io/mii.c b/os/io/mii.c deleted file mode 100644 index da36db9d2..000000000 --- a/os/io/mii.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 mii.c - * @brief mii Driver code. - * @addtogroup MII - * @{ - */ - -#include -#include -#include - -/* - * Currently there is no code, everything is done in the header, you may - * omit this file from the project but this may change in future releases. - * The file is here because the driver's naming pattern. - */ - -/** @} */ diff --git a/os/io/mii.h b/os/io/mii.h deleted file mode 100644 index a236c6dc3..000000000 --- a/os/io/mii.h +++ /dev/null @@ -1,220 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 are borrowed by the Linux include file linux/mii.h: - * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com) - */ - -/** - * @file mii.h - * @brief MII Driver macros and structures. - * @addtogroup MII - * @{ - */ - -#ifndef _MII_H_ -#define _MII_H_ - -#include "mac_lld.h" -#include "mii_lld.h" - -/* - * Generic MII registers. Note, not all registers are present on all PHY - * devices and some extra registers may be present. - */ -#define MII_BMCR 0x00 /**< Basic mode control register. */ -#define MII_BMSR 0x01 /**< Basic mode status register. */ -#define MII_PHYSID1 0x02 /**< PHYS ID 1. */ -#define MII_PHYSID2 0x03 /**< PHYS ID 2. */ -#define MII_ADVERTISE 0x04 /**< Advertisement control reg. */ -#define MII_LPA 0x05 /**< Link partner ability reg. */ -#define MII_EXPANSION 0x06 /**< Expansion register. */ -#define MII_CTRL1000 0x09 /**< 1000BASE-T control. */ -#define MII_STAT1000 0x0a /**< 1000BASE-T status. */ -#define MII_ESTATUS 0x0f /**< Extended Status. */ -#define MII_DCOUNTER 0x12 /**< Disconnect counter. */ -#define MII_FCSCOUNTER 0x13 /**< False carrier counter. */ -#define MII_NWAYTEST 0x14 /**< N-way auto-neg test reg. */ -#define MII_RERRCOUNTER 0x15 /**< Receive error counter. */ -#define MII_SREVISION 0x16 /**< Silicon revision. */ -#define MII_RESV1 0x17 /**< Reserved. */ -#define MII_LBRERROR 0x18 /**< Lpback, rx, bypass error. */ -#define MII_PHYADDR 0x19 /**< PHY address. */ -#define MII_RESV2 0x1a /**< Reserved. */ -#define MII_TPISTATUS 0x1b /**< TPI status for 10mbps. */ -#define MII_NCONFIG 0x1c /**< Network interface config. */ - -/* - * Basic mode control register. - */ -#define BMCR_RESV 0x003f /**< Unused. */ -#define BMCR_SPEED1000 0x0040 /**< MSB of Speed (1000). */ -#define BMCR_CTST 0x0080 /**< Collision test. */ -#define BMCR_FULLDPLX 0x0100 /**< Full duplex. */ -#define BMCR_ANRESTART 0x0200 /**< Auto negotiation restart. */ -#define BMCR_ISOLATE 0x0400 /**< Disconnect DP83840 from MII. */ -#define BMCR_PDOWN 0x0800 /**< Powerdown. */ -#define BMCR_ANENABLE 0x1000 /**< Enable auto negotiation. */ -#define BMCR_SPEED100 0x2000 /**< Select 100Mbps. */ -#define BMCR_LOOPBACK 0x4000 /**< TXD loopback bits. */ -#define BMCR_RESET 0x8000 /**< Reset. */ - -/* - * Basic mode status register. - */ -#define BMSR_ERCAP 0x0001 /**< Ext-reg capability. */ -#define BMSR_JCD 0x0002 /**< Jabber detected. */ -#define BMSR_LSTATUS 0x0004 /**< Link status. */ -#define BMSR_ANEGCAPABLE 0x0008 /**< Able to do auto-negotiation. */ -#define BMSR_RFAULT 0x0010 /**< Remote fault detected. */ -#define BMSR_ANEGCOMPLETE 0x0020 /**< Auto-negotiation complete. */ -#define BMSR_RESV 0x00c0 /**< Unused. */ -#define BMSR_ESTATEN 0x0100 /**< Extended Status in R15. */ -#define BMSR_100HALF2 0x0200 /**< Can do 100BASE-T2 HDX. */ -#define BMSR_100FULL2 0x0400 /**< Can do 100BASE-T2 FDX. */ -#define BMSR_10HALF 0x0800 /**< Can do 10mbps, half-duplex. */ -#define BMSR_10FULL 0x1000 /**< Can do 10mbps, full-duplex. */ -#define BMSR_100HALF 0x2000 /**< Can do 100mbps, half-duplex. */ -#define BMSR_100FULL 0x4000 /**< Can do 100mbps, full-duplex. */ -#define BMSR_100BASE4 0x8000 /**< Can do 100mbps, 4k packets. */ - -/* - * Advertisement control register. - */ -#define ADVERTISE_SLCT 0x001f /**< Selector bits. */ -#define ADVERTISE_CSMA 0x0001 /**< Only selector supported. */ -#define ADVERTISE_10HALF 0x0020 /**< Try for 10mbps half-duplex. */ -#define ADVERTISE_1000XFULL 0x0020 /**< Try for 1000BASE-X full-duplex.*/ -#define ADVERTISE_10FULL 0x0040 /**< Try for 10mbps full-duplex. */ -#define ADVERTISE_1000XHALF 0x0040 /**< Try for 1000BASE-X half-duplex.*/ -#define ADVERTISE_100HALF 0x0080 /**< Try for 100mbps half-duplex. */ -#define ADVERTISE_1000XPAUSE 0x0080 /**< Try for 1000BASE-X pause. */ -#define ADVERTISE_100FULL 0x0100 /**< Try for 100mbps full-duplex. */ -#define ADVERTISE_1000XPSE_ASYM 0x0100 /**< Try for 1000BASE-X asym pause. */ -#define ADVERTISE_100BASE4 0x0200 /**< Try for 100mbps 4k packets. */ -#define ADVERTISE_PAUSE_CAP 0x0400 /**< Try for pause. */ -#define ADVERTISE_PAUSE_ASYM 0x0800 /**< Try for asymetric pause. */ -#define ADVERTISE_RESV 0x1000 /**< Unused. */ -#define ADVERTISE_RFAULT 0x2000 /**< Say we can detect faults. */ -#define ADVERTISE_LPACK 0x4000 /**< Ack link partners response. */ -#define ADVERTISE_NPAGE 0x8000 /**< Next page bit. */ - -#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ - ADVERTISE_CSMA) -#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \ - ADVERTISE_100HALF | ADVERTISE_100FULL) - -/* - * Link partner ability register. - */ -#define LPA_SLCT 0x001f /**< Same as advertise selector. */ -#define LPA_10HALF 0x0020 /**< Can do 10mbps half-duplex. */ -#define LPA_1000XFULL 0x0020 /**< Can do 1000BASE-X full-duplex. */ -#define LPA_10FULL 0x0040 /**< Can do 10mbps full-duplex. */ -#define LPA_1000XHALF 0x0040 /**< Can do 1000BASE-X half-duplex. */ -#define LPA_100HALF 0x0080 /**< Can do 100mbps half-duplex. */ -#define LPA_1000XPAUSE 0x0080 /**< Can do 1000BASE-X pause. */ -#define LPA_100FULL 0x0100 /**< Can do 100mbps full-duplex. */ -#define LPA_1000XPAUSE_ASYM 0x0100 /**< Can do 1000BASE-X pause asym. */ -#define LPA_100BASE4 0x0200 /**< Can do 100mbps 4k packets. */ -#define LPA_PAUSE_CAP 0x0400 /**< Can pause. */ -#define LPA_PAUSE_ASYM 0x0800 /**< Can pause asymetrically. */ -#define LPA_RESV 0x1000 /**< Unused. */ -#define LPA_RFAULT 0x2000 /**< Link partner faulted. */ -#define LPA_LPACK 0x4000 /**< Link partner acked us. */ -#define LPA_NPAGE 0x8000 /**< Next page bit. */ - -#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL) -#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4) - -/* - * Expansion register for auto-negotiation. - */ -#define EXPANSION_NWAY 0x0001 /**< Can do N-way auto-nego. */ -#define EXPANSION_LCWP 0x0002 /**< Got new RX page code word. */ -#define EXPANSION_ENABLENPAGE 0x0004 /**< This enables npage words. */ -#define EXPANSION_NPCAPABLE 0x0008 /**< Link partner supports npage. */ -#define EXPANSION_MFAULTS 0x0010 /**< Multiple faults detected. */ -#define EXPANSION_RESV 0xffe0 /**< Unused. */ - -#define ESTATUS_1000_TFULL 0x2000 /**< Can do 1000BT Full. */ -#define ESTATUS_1000_THALF 0x1000 /**< Can do 1000BT Half. */ - -/* - * N-way test register. - */ -#define NWAYTEST_RESV1 0x00ff /**< Unused. */ -#define NWAYTEST_LOOPBACK 0x0100 /**< Enable loopback for N-way. */ -#define NWAYTEST_RESV2 0xfe00 /**< Unused. */ - -/* - * 1000BASE-T Control register. - */ -#define ADVERTISE_1000FULL 0x0200 /**< Advertise 1000BASE-T full duplex.*/ -#define ADVERTISE_1000HALF 0x0100 /**< Advertise 1000BASE-T half duplex.*/ - -/* - * 1000BASE-T Status register. - */ -#define LPA_1000LOCALRXOK 0x2000 /**< Link partner local receiver status.*/ -#define LPA_1000REMRXOK 0x1000 /**< Link partner remote receiver status.*/ -#define LPA_1000FULL 0x0800 /**< Link partner 1000BASE-T full duplex.*/ -#define LPA_1000HALF 0x0400 /**< Link partner 1000BASE-T half duplex.*/ - -/* - * PHY identifiers. - */ -#define MII_DM9161_ID 0x0181b8a0 -#define MII_AM79C875_ID 0x00225540 -#define MII_KS8721_ID 0x00221610 - -/** - * @brief MII Driver initialization. - */ -#define miiInit() mii_lld_init() - -/** - * Resets a MII device. - * - * @param[in] macp pointer to the @p MACDriver object - */ -#define miiReset(macp) mii_lld_reset(macp) - -/** - * @brief Reads a MII register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param addr the register address - * @return The register value. - */ -#define miiGet(macp, addr) mii_lld_get(macp, addr) - -/** - * @brief Writes a MII register. - * - * @param[in] macp pointer to the @p MACDriver object - * @param addr the register address - * @param value the new register value - */ -#define miiPut(macp, addr, value) mii_lld_put(macp, addr, value) - -#endif /**< _MII_H_ */ - -/** @} */ diff --git a/os/io/mmc_spi.c b/os/io/mmc_spi.c deleted file mode 100644 index 4f6adaf7d..000000000 --- a/os/io/mmc_spi.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 mmc_spi.c - * @brief MMC over SPI driver code - * @addtogroup MMC_SPI - * @{ - */ - -#include -#include -#include - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -void tmrfunc(void *p) { - MMCDriver *mmcp = p; - - if (mmcp->mmc_cnt > 0) { - if (mmcp->mmc_is_inserted()) { - if (--mmcp->mmc_cnt == 0) { - mmcp->mmc_state = MMC_INSERTED; - chEvtBroadcastI(&mmcp->mmc_inserted_event); - } - } - else - mmcp->mmc_cnt = MMC_POLLING_INTERVAL; - } - else { - if (!mmcp->mmc_is_inserted()) { - mmcp->mmc_state = MMC_WAIT; - mmcp->mmc_cnt = MMC_POLLING_INTERVAL; - chEvtBroadcastI(&mmcp->mmc_removed_event); - } - } - chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp); -} - -/** - * @brief Waits an idle condition. - * - * @param[in] mmcp pointer to the @p MMCDriver object - */ -static void wait(MMCDriver *mmcp) { - int i; - uint8_t buf[4]; - - for (i = 0; i < 16; i++) { - spiReceive(mmcp->mmc_spip, 1, buf); - if (buf[0] == 0xFF) - break; - } - /* Looks like it is a long wait.*/ - while (TRUE) { - spiReceive(mmcp->mmc_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 cmd[in] the command id - * @param arg[in] the command argument - */ -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; - buf[5] = 0x95; /* Valid for CMD0 ignored by other commands. */ - spiSend(mmcp->mmc_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. - */ -static uint8_t recvr1(MMCDriver *mmcp) { - int i; - uint8_t r1[1]; - - for (i = 0; i < 9; i++) { - spiReceive(mmcp->mmc_spip, 1, r1); - if (r1[0] != 0xFF) - return r1[0]; - } - return 0xFF; -} - -/** - * @brief Sends a command an returns a single byte response. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param cmd[in] the command id - * @param arg[in] the command argument - * - * @return The response as an @p uint8_t value. - * @retval 0xFF timed out. - */ -static uint8_t send_command(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { - uint8_t r1; - - spiSelect(mmcp->mmc_spip); - send_hdr(mmcp, cmd, arg); - r1 = recvr1(mmcp); - spiUnselect(mmcp->mmc_spip); - return r1; -} - -/** - * @brief Waits that the card reaches an idle state. - * - * @param[in] mmcp pointer to the @p MMCDriver object - */ -static void sync(MMCDriver *mmcp) { - uint8_t buf[1]; - - spiSelect(mmcp->mmc_spip); - while (TRUE) { - spiReceive(mmcp->mmc_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->mmc_spip); -} - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief MMC over SPI driver initialization. - */ -void mmcInit(void) { - -} - -/** - * @brief Initializes an instance. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * @param[in] spip pointer to the SPI driver to be used as interface - * @param[in] lscfg low speed configuration for the SPI driver - * @param[in] hscfg high speed configuration for the SPI driver - * @param[in] is_protected function that returns the card write protection - * setting - * @param[in] is_inserted function that returns the card insertion sensor - * status - */ -void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip, - const SPIConfig *lscfg, const SPIConfig *hscfg, - mmcquery_t is_protected, mmcquery_t is_inserted) { - - mmcp->mmc_state = MMC_STOP; - mmcp->mmc_config = NULL; - mmcp->mmc_spip = spip; - mmcp->mmc_lscfg = lscfg; - mmcp->mmc_hscfg = hscfg; - mmcp->mmc_is_protected = is_protected; - mmcp->mmc_is_inserted = is_inserted; - chEvtInit(&mmcp->mmc_inserted_event); - chEvtInit(&mmcp->mmc_removed_event); -} - -/** - * @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 - */ -void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { - - chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart"); - - chSysLock(); - chDbgAssert(mmcp->mmc_state == MMC_STOP, "mmcStart(), #1", "invalid state"); - mmcp->mmc_config = config; - mmcp->mmc_state = MMC_WAIT; - mmcp->mmc_cnt = MMC_POLLING_INTERVAL; - chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp); - chSysUnlock(); -} - -/** - * @brief Disables the MMC peripheral. - * - * @param[in] mmcp pointer to the @p MMCDriver object - */ -void mmcStop(MMCDriver *mmcp) { - - chDbgCheck(mmcp != NULL, "mmcStop"); - - chSysLock(); - chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && - (mmcp->mmc_state != MMC_READING) && - (mmcp->mmc_state != MMC_WRITING), - "mmcStop(), #1", - "invalid state"); - if (mmcp->mmc_state != MMC_STOP) { - mmcp->mmc_state = MMC_STOP; - chVTResetI(&mmcp->mmc_vt); - } - chSysUnlock(); - spiStop(mmcp->mmc_spip); -} - -/** - * @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 FALSE the operation was successful and the driver is now - * in the @p MMC_READY state. - * @retval TRUE the operation failed. - */ -bool_t mmcConnect(MMCDriver *mmcp) { - unsigned i; - bool_t result; - - chDbgCheck(mmcp != NULL, "mmcConnect"); - - chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && - (mmcp->mmc_state != MMC_STOP), - "mmcConnect(), #1", - "invalid state"); - - if (mmcp->mmc_state == MMC_INSERTED) { - /* Slow clock mode and 128 clock pulses.*/ - spiStart(mmcp->mmc_spip, mmcp->mmc_lscfg); - spiIgnore(mmcp->mmc_spip, 16); - - /* SPI mode selection.*/ - i = 0; - while (TRUE) { - if (send_command(mmcp, MMC_CMDGOIDLE, 0) == 0x01) - break; - if (++i >= MMC_CMD0_RETRY) - return TRUE; - chThdSleepMilliseconds(10); - } - - /* Initialization. */ - i = 0; - while (TRUE) { - uint8_t b = send_command(mmcp, MMC_CMDINIT, 0); - if (b == 0x00) - break; - if (b != 0x01) - return TRUE; - if (++i >= MMC_CMD1_RETRY) - return TRUE; - chThdSleepMilliseconds(10); - } - - /* Initialization complete, full speed. */ - spiStart(mmcp->mmc_spip, mmcp->mmc_hscfg); - - /* Setting block size.*/ - if (send_command(mmcp, MMC_CMDSETBLOCKLEN, MMC_SECTOR_SIZE) != 0x00) - return TRUE; - - /* Transition to MMC_READY state (if not extracted).*/ - chSysLock(); - if (mmcp->mmc_state == MMC_INSERTED) { - mmcp->mmc_state = MMC_READY; - result = FALSE; - } - else - result = TRUE; - chSysUnlock(); - return result; - } - if (mmcp->mmc_state == MMC_READY) - return FALSE; - /* Any other state is invalid.*/ - return TRUE; -} - -/** - * @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 FALSE the operation was successful and the driver is now - * in the @p MMC_INSERTED state. - * @retval TRUE the operation failed. - */ -bool_t mmcDisconnect(MMCDriver *mmcp) { - - chDbgCheck(mmcp != NULL, "mmcConnect"); - - chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && - (mmcp->mmc_state != MMC_STOP), - "mmcDisconnect(), #1", - "invalid state"); - switch (mmcp->mmc_state) { - case MMC_READY: - /* Wait for the pending write operations to complete.*/ - sync(mmcp); - chSysLock(); - if (mmcp->mmc_state == MMC_READY) - mmcp->mmc_state = MMC_INSERTED; - chSysUnlock(); - case MMC_INSERTED: - return FALSE; - default: - return TRUE; - } -} - -/** - * @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 FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { - - chDbgCheck(mmcp != NULL, "mmcStartSequentialRead"); - - chSysLock(); - if (mmcp->mmc_state != MMC_READY) { - chSysUnlock(); - return TRUE; - } - mmcp->mmc_state = MMC_READING; - chSysUnlock(); - - spiSelect(mmcp->mmc_spip); - send_hdr(mmcp, MMC_CMDREADMULTIPLE, startblk * MMC_SECTOR_SIZE); - if (recvr1(mmcp) != 0x00) { - spiUnselect(mmcp->mmc_spip); - chSysLock(); - if (mmcp->mmc_state == MMC_READING) - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return TRUE; - } - return FALSE; -} - -/** - * @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 FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { - int i; - - chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); - - chSysLock(); - if (mmcp->mmc_state != MMC_READING) { - chSysUnlock(); - return TRUE; - } - chSysUnlock(); - - for (i = 0; i < MMC_WAIT_DATA; i++) { - spiReceive(mmcp->mmc_spip, 1, buffer); - if (buffer[0] == 0xFE) { - spiReceive(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer); - /* CRC ignored. */ - spiIgnore(mmcp->mmc_spip, 2); - return FALSE; - } - } - /* Timeout.*/ - spiUnselect(mmcp->mmc_spip); - chSysLock(); - if (mmcp->mmc_state == MMC_READING) - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return TRUE; -} - -/** - * @brief Stops a sequential read gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -bool_t mmcStopSequentialRead(MMCDriver *mmcp) { - static const uint8_t stopcmd[] = {0x40 | MMC_CMDSTOP, 0, 0, 0, 0, 1, 0xFF}; - bool_t result; - - chDbgCheck(mmcp != NULL, "mmcStopSequentialRead"); - - chSysLock(); - if (mmcp->mmc_state != MMC_READING) { - chSysUnlock(); - return TRUE; - } - chSysUnlock(); - - spiSend(mmcp->mmc_spip, sizeof(stopcmd), stopcmd); - result = recvr1(mmcp) != 0x00; - spiUnselect(mmcp->mmc_spip); - - chSysLock(); - if (mmcp->mmc_state == MMC_READING) - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return result; -} - -/** - * @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 FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { - - chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite"); - - chSysLock(); - if (mmcp->mmc_state != MMC_READY) { - chSysUnlock(); - return TRUE; - } - mmcp->mmc_state = MMC_WRITING; - chSysUnlock(); - - spiSelect(mmcp->mmc_spip); - send_hdr(mmcp, MMC_CMDWRITEMULTIPLE, startblk * MMC_SECTOR_SIZE); - if (recvr1(mmcp) != 0x00) { - spiUnselect(mmcp->mmc_spip); - chSysLock(); - if (mmcp->mmc_state == MMC_WRITING) - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return TRUE; - } - return FALSE; -} - -/** - * @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 FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -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), "mmcSequentialRead"); - - chSysLock(); - if (mmcp->mmc_state != MMC_WRITING) { - chSysUnlock(); - return TRUE; - } - chSysUnlock(); - - spiSend(mmcp->mmc_spip, sizeof(start), start); /* Data prologue. */ - spiSend(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer); /* Data. */ - spiIgnore(mmcp->mmc_spip, 2); /* CRC ignored. */ - spiReceive(mmcp->mmc_spip, 1, b); - if ((b[0] & 0x1F) == 0x05) - return FALSE; - - /* Error.*/ - spiUnselect(mmcp->mmc_spip); - chSysLock(); - if (mmcp->mmc_state == MMC_WRITING) - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return TRUE; -} - -/** - * @brief Stops a sequential write gracefully. - * - * @param[in] mmcp pointer to the @p MMCDriver object - * - * @return The operation status. - * @retval FALSE the operation was successful. - * @retval TRUE the operation failed. - */ -bool_t mmcStopSequentialWrite(MMCDriver *mmcp) { - static const uint8_t stop[] = {0xFD, 0xFF}; - - chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite"); - - chSysLock(); - if (mmcp->mmc_state != MMC_WRITING) { - chSysUnlock(); - return TRUE; - } - chSysUnlock(); - - spiSend(mmcp->mmc_spip, sizeof(stop), stop); - spiUnselect(mmcp->mmc_spip); - - chSysLock(); - if (mmcp->mmc_state == MMC_WRITING) { - mmcp->mmc_state = MMC_READY; - chSysUnlock(); - return FALSE; - } - chSysUnlock(); - return TRUE; -} - -/** @} */ diff --git a/os/io/mmc_spi.h b/os/io/mmc_spi.h deleted file mode 100644 index 96e5e3ec5..000000000 --- a/os/io/mmc_spi.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 mmc_spi.h - * @brief MMC over SPI driver header - * @addtogroup MMC_SPI - * @{ - */ - -#ifndef _MMC_SPI_H_ -#define _MMC_SPI_H_ - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Block size for MMC transfers. - */ -#if !defined(MMC_SECTOR_SIZE) || defined(__DOXYGEN__) -#define MMC_SECTOR_SIZE 512 -#endif - -/** - * @brief Delays insertions. - * @details If enabled this options inserts delays into the MMC waiting - * routines releasing some extra CPU time for the threads with - * lower priority, this may slow down the driver a bit however. - * This option is recommended also if the SPI driver does not - * use a DMA channel and heavily loads the CPU. - */ -#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) -#define MMC_NICE_WAITING TRUE -#endif - -/** - * @brief Number of positive insertion queries before generating the - * insertion event. - */ -#if !defined(MMC_POLLING_INTERVAL) || defined(__DOXYGEN__) -#define MMC_POLLING_INTERVAL 10 -#endif - -/** - * @brief Interval, in milliseconds, between insertion queries. - */ -#if !defined(MMC_POLLING_DELAY) || defined(__DOXYGEN__) -#define MMC_POLLING_DELAY 10 -#endif - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -#define MMC_CMD0_RETRY 10 -#define MMC_CMD1_RETRY 100 -#define MMC_WAIT_DATA 10000 - -#define MMC_CMDGOIDLE 0 -#define MMC_CMDINIT 1 -#define MMC_CMDREADCSD 9 -#define MMC_CMDSTOP 12 -#define MMC_CMDSETBLOCKLEN 16 -#define MMC_CMDREAD 17 -#define MMC_CMDREADMULTIPLE 18 -#define MMC_CMDWRITE 24 -#define MMC_CMDWRITEMULTIPLE 25 - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - MMC_UNINIT = 0, /**< @brief Not initialized. */ - MMC_STOP = 1, /**< @brief Stopped. */ - MMC_WAIT = 2, /**< @brief Waiting card. */ - MMC_INSERTED = 3, /**< @brief Card inserted. */ - MMC_READY = 4, /**< @brief Card ready. */ - MMC_READING = 5, /**< @brief Reading. */ - MMC_WRITING = 6 /**< @brief Writing. */ -} mmcstate_t; - -/** - * @brief Function used to query some hardware status bits. - * - * @return The status. - */ -typedef bool_t (*mmcquery_t)(void); - -/** - * @brief Driver configuration structure. - */ -typedef struct { - -} MMCConfig; - -/** - * @brief Structure representing a MMC driver. - */ -typedef struct { - /** - * @brief Driver state. - */ - mmcstate_t mmc_state; - /** - * @brief Current configuration data. - */ - const MMCConfig *mmc_config; - /** - * @brief SPI driver associated to this MMC driver. - */ - SPIDriver *mmc_spip; - /** - * @brief SPI low speed configuration used during initialization. - */ - const SPIConfig *mmc_lscfg; - /** - * @brief SPI high speed configuration used during transfers. - */ - const SPIConfig *mmc_hscfg; - /** - * @brief Write protect status query function. - */ - mmcquery_t mmc_is_protected; - /** - * @brief Insertion status query function. - */ - mmcquery_t mmc_is_inserted; - /** - * @brief Card insertion event source. - */ - EventSource mmc_inserted_event; - /** - * @brief Card removal event source. - */ - EventSource mmc_removed_event; - /** - * @brief MMC insertion polling timer. - */ - VirtualTimer mmc_vt; - /** - * @brief Insertion counter. - */ - uint_fast8_t mmc_cnt; -} MMCDriver; - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -/** - * @brief Returns the driver state. - */ -#define mmcGetDriverState(mmcp) ((mmcp)->mmc_state) - -/** - * @brief Returns the write protect status. - */ -#define mmcIsWriteProtected(mmcp) ((mmcp)->mmc_is_protected()) - -#ifdef __cplusplus -extern "C" { -#endif - void mmcInit(void); - void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip, - const SPIConfig *lscfg, const SPIConfig *hscfg, - mmcquery_t is_protected, mmcquery_t is_inserted); - void mmcStart(MMCDriver *mmcp, const MMCConfig *config); - void mmcStop(MMCDriver *mmcp); - bool_t mmcConnect(MMCDriver *mmcp); - bool_t mmcDisconnect(MMCDriver *mmcp); - bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk); - bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer); - bool_t mmcStopSequentialRead(MMCDriver *mmcp); - bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk); - bool_t mmcSequentialWrite(MMCDriver *mmcp, const uint8_t *buffer); - bool_t mmcStopSequentialWrite(MMCDriver *mmcp); -#ifdef __cplusplus -} -#endif - -#endif /* _MMC_SPI_H_ */ - -/** @} */ diff --git a/os/io/pal.c b/os/io/pal.c deleted file mode 100644 index f7645f621..000000000 --- a/os/io/pal.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/** - * @brief Read from an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return The bus logical states. - * - * @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. - */ -ioportmask_t palReadBus(IOBus *bus) { - - chDbgCheck((bus != NULL) && - (bus->bus_offset > PAL_IOPORTS_WIDTH), "palReadBus"); - - return palReadGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset); -} - -/** - * @brief Write to an I/O bus. - * - * @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. - * - * @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. - */ -void palWriteBus(IOBus *bus, ioportmask_t bits) { - - chDbgCheck((bus != NULL) && - (bus->bus_offset > PAL_IOPORTS_WIDTH), "palWriteBus"); - - palWriteGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset, bits); -} - -/** - * @brief Programs a bus with the specified mode. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] mode the 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. - */ -void palSetBusMode(IOBus *bus, uint_fast8_t mode) { - - chDbgCheck((bus != NULL) && - (bus->bus_offset > PAL_IOPORTS_WIDTH), "palSetBusMode"); - - palSetGroupMode(bus->bus_portid, bus->bus_mask, mode); -} - -/** @} */ diff --git a/os/io/pal.h b/os/io/pal.h deleted file mode 100644 index 67bc424b1..000000000 --- a/os/io/pal.h +++ /dev/null @@ -1,467 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief I/O Ports Abstraction Layer macros, types and structures - * @addtogroup PAL - * @{ - */ - -#ifndef _PAL_H_ -#define _PAL_H_ - -/** - * @brief Bits in a mode word dedicated as mode selector. - * @details The other bits are not defined and may be used as device-specific - * option bits. - */ -#define PAL_MODE_MASK 0xF - -/** - * @brief After reset state. - * @details The state itself is not specified and is architecture dependent, - * it is guaranteed to be equal to the after-reset state. It is - * usually an input state. - */ -#define PAL_MODE_RESET 0 - -/** - * @brief Safe state for unconnected pads. - * @details The state itself is not specified and is architecture dependent, - * it may be mapped on @p PAL_MODE_INPUT_PULLUP, - * @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL as - * example. - */ -#define PAL_MODE_UNCONNECTED 1 - -/** - * @brief Regular input high-Z pad. - */ -#define PAL_MODE_INPUT 2 - -/** - * @brief Input pad with weak pull up resistor. - */ -#define PAL_MODE_INPUT_PULLUP 3 - -/** - * @brief Input pad with weak pull down resistor. - */ -#define PAL_MODE_INPUT_PULLDOWN 4 - -/** - * @brief Analog input mode. - */ -#define PAL_MODE_INPUT_ANALOG 5 - -/** - * @brief Push-pull output pad. - */ -#define PAL_MODE_OUTPUT_PUSHPULL 6 - -/** - * @brief Open-drain output pad. - */ -#define PAL_MODE_OUTPUT_OPENDRAIN 7 - -#ifndef _PAL_LLD_H_ -#include "pal_lld.h" -#endif - -/** - * @brief Logical low state. - */ -#define PAL_LOW 0 - -/** - * @brief Logical high state. - */ -#define PAL_HIGH 1 - -/** - * @brief Port bit helper macro. - * @details This macro calculates the mask of a bit within a port. - * - * @param[in] n the bit position within the port - * @return The bit mask. - */ -#define PAL_PORT_BIT(n) ((ioportmask_t)(1 << (n))) - - -/** - * @brief Bits group mask helper. - * @details This macro calculates the mask of a bits group. - * - * @param[in] width the group width - * @return The group mask. - */ -#define PAL_GROUP_MASK(width) ((ioportmask_t)(1 << (width)) - 1) - -/** - * @brief Data part of a static I/O bus initializer. - * @details This macro should be used when statically initializing an I/O bus - * that is part of a bigger structure. - * - * @param name the name of the IOBus variable - * @param port the I/O port descriptor - * @param width the bus width in bits - * @param offset the bus bit offset within the port - */ -#define _IOBUS_DATA(name, port, width, offset) \ - {port, PAL_GROUP_MASK(width), offset} - -/** - * @brief Static I/O bus initializer. - * - * @param name the name of the IOBus variable - * @param port the I/O port descriptor - * @param width the bus width in bits - * @param offset the bus bit offset within the port - */ -#define IOBUS_DECL(name, port, width, offset) \ - IOBus name = _IOBUS_DATA(name, port, width, offset) - -/** - * @brief I/O bus descriptor. - * @details This structure describes a group of contiguous digital I/O lines - * that have to be handled as bus. - * @note I/O operations on a bus do not affect I/O lines on the same port but - * not belonging to the bus. - */ -typedef struct { - /** Port identifier.*/ - ioportid_t bus_portid; - /** Bus mask aligned to port bit 0. The bus mask implicitly define the bus - width. A logical AND is performed on the bus data.*/ - ioportmask_t bus_mask; - /** Offset, within the port, of the least significant bit of the bus.*/ - uint_fast8_t bus_offset; -} IOBus; - -/** - * @brief PAL subsystem initialization. - * - * @param[in] config pointer to an architecture specific configuration - * structure. This structure is defined in the low level driver - * header. - */ -#define palInit(config) pal_lld_init(config) - -/** - * @brief Reads the physical I/O port states. - * - * @param[in] port the port identifier - * @return The port logical states. - * - * @note The default implementation always return zero and computes the - * parameter eventual side effects. - */ -#if !defined(pal_lld_readport) || defined(__DOXYGEN__) -#define palReadPort(port) ((void)(port), 0) -#else -#define palReadPort(port) pal_lld_readport(port) -#endif - -/** - * @brief Reads the output latch. - * @details The purpose of this function is to read back the latched output - * value. - * - * @param[in] port the port identifier - * @return The latched logical states. - * - * @note The default implementation always return zero and computes the - * parameter eventual side effects. - */ -#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__) -#define palReadLatch(port) ((void)(port), 0) -#else -#define palReadLatch(port) pal_lld_readlatch(port) -#endif - -/** - * @brief Writes a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be written on the specified port - * - * @note The default implementation does nothing except computing the - * parameters eventual side effects. - */ -#if !defined(pal_lld_writeport) || defined(__DOXYGEN__) -#define palWritePort(port, bits) ((void)(port), (void)(bits)) -#else -#define palWritePort(port, bits) pal_lld_writeport(port, bits) -#endif - -/** - * @brief Sets a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be ORed on the specified port - * - * @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. - */ -#if !defined(pal_lld_setport) || defined(__DOXYGEN__) -#define palSetPort(port, bits) { \ - palWritePort(port, palReadLatch(port) | (bits)); \ -} -#else -#define palSetPort(port, bits) pal_lld_setport(port, bits) -#endif - -/** - * @brief Clears a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be cleared on the specified port - * - * @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. - */ -#if !defined(pal_lld_clearport) || defined(__DOXYGEN__) -#define palClearPort(port, bits) { \ - palWritePort(port, palReadLatch(port) & ~(bits)); \ -} -#else -#define palClearPort(port, bits) pal_lld_clearport(port, bits) -#endif - -/** - * @brief Toggles a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be XORed on the specified port - * - * @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. - */ -#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__) -#define palTogglePort(port, bits) { \ - palWritePort(port, palReadLatch(port) ^ (bits)); \ -} -#else -#define palTogglePort(port, bits) pal_lld_toggleport(port, bits) -#endif - -/** - * @brief Reads a group of bits. - * - * @param[in] port the port identifier - * @param[in] mask the group mask, a logical AND is performed on the input - * data - * @param[in] offset the group bit offset within the port - * @return The group logical states. - */ -#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__) -#define palReadGroup(port, mask, offset) \ - ((palReadPort(port) >> (offset)) & (mask)) -#else -#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset) -#endif - -/** - * @brief Writes a group of bits. - * - * @param[in] port the port identifier - * @param[in] mask the group mask, a logical AND is performed on the output - * data - * @param[in] offset the group bit offset within the port - * @param[in] bits the bits to be written. Values exceeding the group width - * are masked. - */ -#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__) -#define palWriteGroup(port, mask, offset, bits) { \ - palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \ - (((bits) & (mask)) << (offset))); \ -} -#else -#define palWriteGroup(port, mask, offset, bits) \ - pal_lld_writegroup(port, mask, offset, bits) -#endif - - -/** - * @brief Pads group mode setup. - * @details This function programs a pads group belonging to the same port - * with the specified mode. - * - * @param[in] port the port identifier - * @param[in] mask the group mask - * @param[in] mode the setup mode - * - * @note Programming an unknown or unsupported mode is silently ignored. - */ -#if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__) -#define palSetGroupMode(port, mask, mode) -#else -#define palSetGroupMode(port, mask, mode) pal_lld_setgroupmode(port, mask, mode) -#endif - -/** - * @brief Reads an input pad logical state. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * @return The logical state. - * @retval 0 low logical state. - * @retval 1 high logical state. - * - * @note The default implementation not necessarily optimal. Low level drivers - * may optimize the function by using specific hardware or coding. - * @note The default implementation internally uses the @p palReadPort(). - */ -#if !defined(pal_lld_readpad) || defined(__DOXYGEN__) -#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1) -#else -#define palReadPad(port, pad) pal_lld_readpad(port, pad) -#endif - -/** - * @brief Writes a logical state on an output pad. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * @param[out] bit the logical value, the value must be @p 0 or @p 1 - * - * @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. - * @note The default implementation internally uses the @p palReadLatch() and - * @p palWritePort(). - */ -#if !defined(pal_lld_writepad) || defined(__DOXYGEN__) -#define palWritePad(port, pad, bit) { \ - palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \ - (((bit) & 1) << pad)); \ -} -#else -#define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit) -#endif - -/** - * @brief Sets a pad logical state to @p 1. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @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. - * @note The default implementation internally uses the @p palSetPort(). - */ -#if !defined(pal_lld_setpad) || defined(__DOXYGEN__) -#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad)) -#else -#define palSetPad(port, pad) pal_lld_setpad(port, pad) -#endif - -/** - * @brief Clears a pad logical state to @p 0. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @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. - * @note The default implementation internally uses the @p palClearPort(). - */ -#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__) -#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad)) -#else -#define palClearPad(port, pad) pal_lld_clearpad(port, pad) -#endif - -/** - * @brief Toggles a pad logical state. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @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. - * @note The default implementation internally uses the @p palTogglePort(). - */ -#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__) -#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad)) -#else -#define palTogglePad(port, pad) pal_lld_togglepad(port, pad) -#endif - - -/** - * @brief Pad mode setup. - * @details This function programs a pad with the specified mode. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * @param[in] mode the setup mode - * - * @note The default implementation not necessarily optimal. Low level drivers - * may optimize the function by using specific hardware or coding. - * @note Programming an unknown or unsupported mode is silently ignored. - */ -#if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__) -#define palSetPadMode(port, pad, mode) \ - palSetGroupMode(port, PAL_PORT_BIT(pad), mode) -#else -#define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - ioportmask_t palReadBus(IOBus *bus); - void palWriteBus(IOBus *bus, ioportmask_t bits); - void palSetBusMode(IOBus *bus, uint_fast8_t mode); -#ifdef __cplusplus -} -#endif - -#endif /* _PAL_H_ */ - -/** @} */ diff --git a/os/io/serial.c b/os/io/serial.c deleted file mode 100644 index 9c398f5f0..000000000 --- a/os/io/serial.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/* - * Interface implementation, the following functions just invoke the equivalent - * queue-level function or macro. - */ -static bool_t putwouldblock(void *ip) { - - return chOQIsFull(&((SerialDriver *)ip)->d2.oqueue); -} - -static bool_t getwouldblock(void *ip) { - - return chIQIsEmpty(&((SerialDriver *)ip)->d2.iqueue); -} - -static msg_t put(void *ip, uint8_t b, systime_t timeout) { - - return chOQPutTimeout(&((SerialDriver *)ip)->d2.oqueue, b, timeout); -} - -static msg_t get(void *ip, systime_t timeout) { - - return chIQGetTimeout(&((SerialDriver *)ip)->d2.iqueue, timeout); -} - -static size_t write(void *ip, uint8_t *buffer, size_t n) { - - return chOQWrite(&((SerialDriver *)ip)->d2.oqueue, buffer, n); -} - -static size_t read(void *ip, uint8_t *buffer, size_t n) { - - return chIQRead(&((SerialDriver *)ip)->d2.iqueue, buffer, n); -} - -static const struct SerialDriverVMT vmt = { - {putwouldblock, getwouldblock, put, get}, - {write, read}, - {} -}; - -/** - * @brief Serial Driver initialization. - */ -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. - */ -void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { - - sdp->vmt = &vmt; - chEvtInit(&sdp->d1.ievent); - chEvtInit(&sdp->d1.oevent); - chEvtInit(&sdp->d2.sevent); - sdp->d2.flags = SD_NO_ERROR; - chIQInit(&sdp->d2.iqueue, sdp->d2.ib, SERIAL_BUFFERS_SIZE, inotify); - chOQInit(&sdp->d2.oqueue, sdp->d2.ob, SERIAL_BUFFERS_SIZE, onotify); -} - -/** - * @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. - */ -void sdStart(SerialDriver *sdp, const SerialDriverConfig *config) { - - chSysLock(); - sd_lld_start(sdp, config); - 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 SerialDrive object - */ -void sdStop(SerialDriver *sdp) { - - chSysLock(); - sd_lld_stop(sdp); - chOQResetI(&sdp->d2.oqueue); - chIQResetI(&sdp->d2.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. - * @param[in] sd pointer to a @p SerialDriver structure - * @param[in] b the byte to be written in the driver's Input Queue - */ -void sdIncomingDataI(SerialDriver *sd, uint8_t b) { - - if (chIQPutI(&sd->d2.iqueue, b) < Q_OK) - sdAddFlagsI(sd, SD_OVERRUN_ERROR); - else - chEvtBroadcastI(&sd->d1.ievent); -} - -/** - * @brief Handles outgoing data. - * @details Must be called from the output interrupt service routine in order - * to get the next byte to be transmitted. - * - * @param[in] sd 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). - */ -msg_t sdRequestDataI(SerialDriver *sd) { - - msg_t b = chOQGetI(&sd->d2.oqueue); - if (b < Q_OK) - chEvtBroadcastI(&sd->d1.oevent); - return b; -} - -/** - * @brief Handles communication events/errors. - * @details Must be called from the I/O interrupt service routine in order to - * notify I/O conditions as errors, signals change etc. - * - * @param[in] sd pointer to a @p SerialDriver structure - * @param[in] mask condition flags to be added to the mask - */ -void sdAddFlagsI(SerialDriver *sd, sdflags_t mask) { - - sd->d2.flags |= mask; - chEvtBroadcastI(&sd->d2.sevent); -} - -/** - * @brief Returns and clears the errors mask associated to the driver. - * - * @param[in] sd pointer to a @p SerialDriver structure - * @return The condition flags modified since last time this function was - * invoked. - */ -sdflags_t sdGetAndClearFlags(SerialDriver *sd) { - sdflags_t mask; - - mask = sd->d2.flags; - sd->d2.flags = SD_NO_ERROR; - return mask; -} - -/** @} */ diff --git a/os/io/serial.h b/os/io/serial.h deleted file mode 100644 index 6324a5f5b..000000000 --- a/os/io/serial.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief Serial Driver macros and structures. - * @addtogroup SERIAL - * @{ - */ - -#ifndef _SERIAL_H_ -#define _SERIAL_H_ - -/** No pending conditions.*/ -#define SD_NO_ERROR 0 -/** Connection happened.*/ -#define SD_CONNECTED 1 -/** Disconnection happened.*/ -#define SD_DISCONNECTED 2 -/** Parity error happened.*/ -#define SD_PARITY_ERROR 4 -/** Framing error happened.*/ -#define SD_FRAMING_ERROR 8 -/** Overflow happened.*/ -#define SD_OVERRUN_ERROR 16 -/** Break detected.*/ -#define SD_BREAK_DETECTED 32 - -/** - * @brief Structure representing a serial driver. - */ -typedef struct _SerialDriver SerialDriver; - -#include "serial_lld.h" - -/** - * @brief @p SerialDriver specific methods. - */ -struct _serial_driver_methods { -}; - -/** - * @brief @p SerialDriver virtual methods table. - */ -struct SerialDriverVMT { - /** - * @p BaseChannel class inherited methods. - */ - struct _base_channel_methods m0; - /** - * @p BaseAsynchronousChannel class inherited methods. - */ - struct _base_asynchronous_channel_methods m1; - /** - * @p SerialDriver specific methods. - */ - struct _serial_driver_methods m2; -}; - -/** - * @extends BaseAsynchronousChannel - * - * @brief Full duplex serial driver class. - * @details This class extends @p BaseAsynchronousChannel by adding physical - * I/O queues. - */ -struct _SerialDriver { - /** - * Virtual Methods Table. - */ - const struct SerialDriverVMT *vmt; - /** - * @p BaseChannel class inherited data. - */ - struct _base_channel_data d0; - /** - * @p BaseAsynchronousChannel class inherited data. - */ - struct _base_asynchronous_channel_data d1; - /** - * @p SerialDriver specific data. - */ - struct _serial_driver_data d2; -}; - -#ifdef __cplusplus -extern "C" { -#endif - void sdInit(void); - void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify); - void sdStart(SerialDriver *sdp, const SerialDriverConfig *config); - void sdStop(SerialDriver *sdp); - void sdIncomingDataI(SerialDriver *sdp, uint8_t b); - msg_t sdRequestDataI(SerialDriver *sdp); - void sdAddFlagsI(SerialDriver *sdp, sdflags_t mask); - sdflags_t sdGetAndClearFlags(SerialDriver *sdp); -#ifdef __cplusplus -} -#endif - -/** - * @brief Direct output check on a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * checks directly the output queue. This is faster but cannot - * be used to check different channels implementations. - * @see chIOPutWouldBlock() - */ -#define sdPutWouldBlock(sdp) chOQIsFull(&(sdp)->d2.oqueue) - -/** - * @brief Direct input check on a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * checks directly the input queue. This is faster but cannot - * be used to check different channels implementations. - * @see chIOGetWouldBlock() - */ -#define sdGetWouldBlock(sdp) chIQIsEmpty(&(sdp)->d2.iqueue) - -/** - * @brief Direct blocking write to a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * writes directly on the output queue. This is faster but cannot - * be used to write to different channels implementations. - * @see chIOPut() - */ -#define sdPut(sdp, b) chOQPut(&(sdp)->d2.oqueue, b) - -/** - * @brief Direct blocking write on a @p SerialDriver with timeout - * specification. - * @details This function bypasses the indirect access to the channel and - * writes directly on the output queue. This is faster but cannot - * be used to write to different channels implementations. - * @see chIOPutTimeout() - */ -#define sdPutTimeout(sdp, b, t) chOQPutTimeout(&(sdp)->d2.iqueue, b, t) - -/** - * @brief Direct blocking read from a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * @see chIOGet() - */ -#define sdGet(sdp) chIQGet(&(sdp)->d2.iqueue) - -/** - * @brief Direct blocking read from a @p SerialDriver with timeout - * specification. - * @details This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * @see chIOGetTimeout() - */ -#define sdGetTimeout(sdp, t) chIQGetTimeout(&(sdp)->d2.iqueue, t) - -/** - * @brief Direct non-blocking write to a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * writes directly to the output queue. This is faster but cannot - * be used to write from different channels implementations. - * @see chIOWrite() - */ -#define sdWrite(sdp, b, n) chOQWrite(&(sdp)->d2.oqueue, b, n) - -/** - * @brief Direct non-blocking read on a @p SerialDriver. - * @details This function bypasses the indirect access to the channel and - * reads directly from the input queue. This is faster but cannot - * be used to read from different channels implementations. - * @see chIORead() - */ -#define sdRead(sdp, b, n) chIQRead(&(sdp)->d2.iqueue, b, n) - -#endif /* _SERIAL_H_ */ - -/** @} */ diff --git a/os/io/spi.c b/os/io/spi.c deleted file mode 100644 index 4d45d217d..000000000 --- a/os/io/spi.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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 -#include - -/** - * @brief SPI Driver initialization. - */ -void spiInit(void) { - - spi_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p SPIDriver structure. - * - * @param[in] spip pointer to the @p SPIDriver object - */ -void spiObjectInit(SPIDriver *spip) { - - spip->spd_state = SPI_STOP; -#if CH_USE_MUTEXES - chMtxInit(&spip->spd_mutex); -#elif CH_USE_SEMAPHORES - chSemInit(&spip->spd_semaphore, 1); -#endif - spip->spd_config = NULL; -} - -/** - * @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 - */ -void spiStart(SPIDriver *spip, const SPIConfig *config) { - - chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); - - chSysLock(); - chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), - "spiStart(), #1", - "invalid state"); - spip->spd_config = config; - spi_lld_start(spip); - spip->spd_state = SPI_READY; - chSysUnlock(); -} - -/** - * @brief Deactivates the SPI peripheral. - * - * @param[in] spip pointer to the @p SPIDriver object - */ -void spiStop(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiStop"); - - chSysLock(); - chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), - "spiStop(), #1", - "invalid state"); - spi_lld_stop(spip); - spip->spd_state = SPI_STOP; - chSysUnlock(); -} - -/** - * @brief Asserts the slave select signal and prepares for transfers. - * - * @param[in] spip pointer to the @p SPIDriver object - */ -void spiSelect(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiSelect"); - - chSysLock(); - chDbgAssert((spip->spd_state == SPI_READY) || - (spip->spd_state == SPI_ACTIVE), - "spiSelect(), #1", - "not idle"); - spi_lld_select(spip); - spip->spd_state = SPI_ACTIVE; - chSysUnlock(); -} - -/** - * @brief Deasserts the slave select signal. - * @details The previously selected peripheral is unselected. - * - * @param[in] spip pointer to the @p SPIDriver object - */ -void spiUnselect(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiUnselect"); - - chSysLock(); - chDbgAssert((spip->spd_state == SPI_READY) || - (spip->spd_state == SPI_ACTIVE), - "spiUnselect(), #1", - "not locked"); - spi_lld_unselect(spip); - spip->spd_state = SPI_READY; - chSysUnlock(); -} - -/** - * @brief Ignores data on the SPI bus. - * @details This function transmits a series of idle words on the SPI bus and - * ignores the received data. This function can be invoked even - * when a slave select signal has not been yet asserted. - * - * @param[in] spip pointer to the @p SPIDriver object - * @param[in] n number of words to be ignored - */ -void spiIgnore(SPIDriver *spip, size_t n) { - - chDbgCheck((spip != NULL) && (n > 0), "spiIgnore"); - chDbgAssert((spip->spd_state == SPI_READY) || (spip->spd_state == SPI_ACTIVE), - "spiIgnore(), #1", - "not active"); - - spi_lld_ignore(spip, n); -} - -/** - * @brief Exchanges data on the SPI bus. - * @details This function performs a simultaneous transmit/receive operation. - * - * @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 - * - * @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. - */ -void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), - "spiExchange"); - chDbgAssert(spip->spd_state == SPI_ACTIVE, - "spiExchange(), #1", - "not active"); - - spi_lld_exchange(spip, n, txbuf, rxbuf); -} - -/** - * @brief Sends data ever the SPI bus. - * - * @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 - * - * @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. - */ -void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), - "spiSend"); - chDbgAssert(spip->spd_state == SPI_ACTIVE, - "spiSend(), #1", - "not active"); - - spi_lld_send(spip, n, txbuf); -} - -/** - * @brief Receives data from the SPI bus. - * - * @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 - * - * @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. - */ -void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { - - chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), - "spiReceive"); - chDbgAssert(spip->spd_state == SPI_ACTIVE, - "spiReceive(), #1", - "not active"); - - spi_lld_receive(spip, n, rxbuf); -} - -#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. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION - * option is set to @p TRUE. - */ -void spiAcquireBus(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiAcquireBus"); - -#if CH_USE_MUTEXES - chMtxLock(&spip->spd_mutex); -#elif CH_USE_SEMAPHORES - chSemWait(&spip->spd_semaphore); -#endif -} - -/** - * @brief Releases exclusive access to the SPI bus. - * - * @param[in] spip pointer to the @p SPIDriver object - * - * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION - * option is set to @p TRUE. - */ -void spiReleaseBus(SPIDriver *spip) { - - chDbgCheck(spip != NULL, "spiReleaseBus"); - -#if CH_USE_MUTEXES - (void)spip; - chMtxUnlock(); -#elif CH_USE_SEMAPHORES - chSemSignal(&spip->spd_semaphore); -#endif -} -#endif /*SPI_USE_MUTUAL_EXCLUSION */ - -/** @} */ diff --git a/os/io/spi.h b/os/io/spi.h deleted file mode 100644 index cebde453f..000000000 --- a/os/io/spi.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 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.h - * @brief SPI Driver macros and structures. - * @addtogroup SPI - * @{ - */ - -#ifndef _SPI_H_ -#define _SPI_H_ - -/** - * @brief Enables the mutual exclusion APIs on the SPI bus. - */ -#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define SPI_USE_MUTUAL_EXCLUSION TRUE -#endif - -#if SPI_USE_MUTUAL_EXCLUSION && !CH_USE_MUTEXES && !CH_USE_SEMAPHORES -#error "SPI_USE_MUTUAL_EXCLUSION requires CH_USE_MUTEXES and/or CH_USE_SEMAPHORES" -#endif - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - SPI_UNINIT = 0, /**< @brief Not initialized. */ - SPI_STOP = 1, /**< @brief Stopped. */ - SPI_READY = 2, /**< @brief Ready. */ - SPI_ACTIVE = 3 /**< @brief Slave selected. */ -} spistate_t; - -#include "spi_lld.h" - -#ifdef __cplusplus -extern "C" { -#endif - void spiInit(void); - void spiObjectInit(SPIDriver *spip); - void spiStart(SPIDriver *spip, const SPIConfig *config); - void spiStop(SPIDriver *spip); - void spiSelect(SPIDriver *spip); - void spiUnselect(SPIDriver *spip); - void spiIgnore(SPIDriver *spip, size_t n); - void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); - void spiSend(SPIDriver *spip, size_t n, const void *txbuf); - void spiReceive(SPIDriver *spip, size_t n, void *rxbuf); -#if SPI_USE_MUTUAL_EXCLUSION - void spiAcquireBus(SPIDriver *spip); - void spiReleaseBus(SPIDriver *spip); -#endif /* SPI_USE_MUTUAL_EXCLUSION */ -#ifdef __cplusplus -} -#endif - -#endif /* _SPI_H_ */ - -/** @} */ diff --git a/os/io/src/adc.c b/os/io/src/adc.c new file mode 100644 index 000000000..af4508ab7 --- /dev/null +++ b/os/io/src/adc.c @@ -0,0 +1,204 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/** + * @brief ADC Driver initialization. + */ +void adcInit(void) { + + adc_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p ADCDriver structure. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +void adcObjectInit(ADCDriver *adcp) { + + adcp->ad_state = ADC_STOP; + adcp->ad_config = NULL; + adcp->ad_callback = NULL; + adcp->ad_samples = NULL; + adcp->ad_depth = 0; + adcp->ad_grpp = NULL; + chSemInit(&adcp->ad_sem, 0); +} + +/** + * @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 + */ +void adcStart(ADCDriver *adcp, const ADCConfig *config) { + + chDbgCheck((adcp != NULL) && (config != NULL), "adcStart"); + + chSysLock(); + chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY), + "adcStart(), #1", + "invalid state"); + adcp->ad_config = config; + adc_lld_start(adcp); + adcp->ad_state = ADC_READY; + chSysUnlock(); +} + +/** + * @brief Deactivates the ADC peripheral. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +void adcStop(ADCDriver *adcp) { + + chDbgCheck(adcp != NULL, "adcStop"); + + chSysLock(); + chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY), + "adcStop(), #1", + "invalid state"); + adc_lld_stop(adcp); + adcp->ad_state = ADC_STOP; + chSysUnlock(); +} + +/** + * @brief Starts an ADC conversion. + * @details Starts a conversion operation, there are two kind of conversion + * modes: + * - LINEAR, this mode is activated when the @p callback + * parameter is set to @p NULL, in this mode the buffer is filled + * once and then the conversion stops automatically. + * - CIRCULAR, when a callback function is defined the + * conversion never stops and the buffer is filled circularly. + * During the conversion the callback function is invoked when + * the buffer is 50% filled and when the buffer is 100% filled, + * this way is possible to process the conversion stream in real + * time. This kind of conversion can only be stopped by explicitly + * invoking @p adcStopConversion(). + * . + * + * @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. + * @param[in] callback pointer to the conversion callback function + * @return The operation status. + * @retval FALSE the conversion has been started. + * @retval TRUE the driver is busy, conversion not started. + * + * @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. + */ +bool_t adcStartConversion(ADCDriver *adcp, + const ADCConversionGroup *grpp, + adcsample_t *samples, + size_t depth, + adccallback_t callback) { + + chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && + ((depth == 1) || ((depth & 1) == 0)), + "adcStartConversion"); + + chSysLock(); + chDbgAssert((adcp->ad_state == ADC_READY) || + (adcp->ad_state == ADC_RUNNING), + "adcStartConversion(), #1", + "invalid state"); + if (adcp->ad_state == ADC_RUNNING) { + chSysUnlock(); + return TRUE; + } + adcp->ad_callback = callback; + adcp->ad_samples = samples; + adcp->ad_depth = depth; + adcp->ad_grpp = grpp; + adc_lld_start_conversion(adcp); + adcp->ad_state = ADC_RUNNING; + chSysUnlock(); + return FALSE; +} + +/** + * @brief Stops an ongoing conversion. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +void adcStopConversion(ADCDriver *adcp) { + + chDbgCheck(adcp != NULL, "adcStopConversion"); + + chSysLock(); + chDbgAssert((adcp->ad_state == ADC_READY) || + (adcp->ad_state == ADC_RUNNING), + "adcStopConversion(), #1", + "invalid state"); + if (adcp->ad_state == ADC_RUNNING) { + adc_lld_stop_conversion(adcp); + adcp->ad_grpp = NULL; + adcp->ad_state = ADC_READY; + } + chSysUnlock(); +} + +/** + * @brief Waits for completion. + * + * @param[in] adcp pointer to the @p ADCDriver object + * @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 conversion finished (or not started). + * @retval RDY_TIMEOUT conversion not finished within the specified time. + */ +msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout) { + + chSysLock(); + chDbgAssert((adcp->ad_state == ADC_READY) || + (adcp->ad_state == ADC_RUNNING), + "adcWaitConversion(), #1", + "invalid state"); + if (adcp->ad_state == ADC_RUNNING) { + if (chSemWaitTimeoutS(&adcp->ad_sem, timeout) == RDY_TIMEOUT) { + chSysUnlock(); + return RDY_TIMEOUT; + } + } + chSysUnlock(); + return RDY_OK; +} + +/** @} */ diff --git a/os/io/src/can.c b/os/io/src/can.c new file mode 100644 index 000000000..4c88f9c71 --- /dev/null +++ b/os/io/src/can.c @@ -0,0 +1,220 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/** + * @brief CAN Driver initialization. + */ +void canInit(void) { + + can_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p CANDriver structure. + * + * @param[in] canp pointer to the @p CANDriver object + */ +void canObjectInit(CANDriver *canp) { + + canp->can_state = CAN_STOP; + canp->can_config = NULL; + chSemInit(&canp->can_txsem); + chSemInit(&canp->can_rxsem); + chEvtInit(&canp->can_rxfull_event); + chEvtInit(&canp->can_txempty_event); +#if CAN_USE_SLEEP_MODE + chEvtInit(&canp->can_sleep_event); + chEvtInit(&canp->can_wakeup_event); +#endif /* CAN_USE_SLEEP_MODE */ +} + +/** + * @brief Configures and activates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + * @param[in] config pointer to the @p CANConfig object + */ +void canStart(CANDriver *canp, const CANConfig *config) { + + chDbgCheck((canp != NULL) && (config != NULL), "canStart"); + + chSysLock(); + chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), + "canStart(), #1", + "invalid state"); + canp->can_config = config; + can_lld_start(canp); + canp->can_state = CAN_READY; + chSysUnlock(); +} + +/** + * @brief Deactivates the CAN peripheral. + * + * @param[in] canp pointer to the @p CANDriver object + */ +void canStop(CANDriver *canp) { + + chDbgCheck(canp != NULL, "canStop"); + + chSysLock(); + chDbgAssert((canp->can_state == CAN_STOP) || (canp->can_state == CAN_READY), + "canStop(), #1", + "invalid state"); + can_lld_stop(canp); + canp->can_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] cfp 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 operation not finished within the specified time. + * @retval RDY_RESET driver stopped while waiting. + */ +msg_t canTransmit(CANDriver *canp, const CANFrame *cfp, systime_t timeout) { + msg_t msg; + + chDbgCheck((canp != NULL) && (cfp != NULL), "canTransmit"); + + chSysLock(); + chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + "canTransmit(), #1", + "invalid state"); + if ((canp->can_state == CAN_SLEEP) || !can_lld_can_transmit(canp)) { + msg = chSemWaitTimeoutS(&canp->can_txsem, timeout); + if (msg != RDY_OK) { + chSysUnlock(); + return msg; + } + } + msg = can_lld_transmit(canp, cfp); + chSysUnlock(); + return msg; +} + +/** + * @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[out] cfp 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. + * - @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 operation not finished within the specified time. + * @retval RDY_RESET driver stopped while waiting. + */ +msg_t canReceive(CANDriver *canp, CANFrame *cfp, systime_t timeout) { + msg_t msg; + + chDbgCheck((canp != NULL) && (cfp != NULL), "canReceive"); + + chSysLock(); + chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + "canReceive(), #1", + "invalid state"); + if ((canp->can_state == CAN_SLEEP) || !can_lld_can_receive(canp)) { + msg = chSemWaitTimeoutS(&canp->can_rxsem, timeout); + if (msg != RDY_OK) { + chSysUnlock(); + return msg; + } + } + msg = can_lld_receive(canp, cfp); + chSysUnlock(); + return msg; +} + +#if CAN_USE_SLEEP_MODE || defined(__DOXYGEN__) +/** + * @brief Enters the sleep mode. + * + * @param[in] canp pointer to the @p CANDriver object + */ +void canSleep(CANDriver *canp) { + + chDbgCheck(canp != NULL, "canSleep"); + + chSysLock(); + chDbgAssert((canp->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + "canSleep(), #1", + "invalid state"); + if (canp->can_state = CAN_READY) { + can_lld_sleep(canp); + canp->can_state = CAN_SLEEP; + chEvtBroadcastI(&canp->can_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->can_state == CAN_READY) || (canp->can_state == CAN_SLEEP), + "canWakeup(), #1", + "invalid state"); + if (canp->can_state = CAN_SLEEP) { + can_lld_wakeup(canp); + canp->can_state = CAN_READY; + chEvtBroadcastI(&canp->can_wakeup_event); + chSchRescheduleS(); + } + chSysUnlock(); +} +#endif /* CAN_USE_SLEEP_MODE */ + +/** @} */ diff --git a/os/io/src/mac.c b/os/io/src/mac.c new file mode 100644 index 000000000..01541682e --- /dev/null +++ b/os/io/src/mac.c @@ -0,0 +1,174 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/** + * @brief MAC Driver initialization. + */ +void macInit(void) { + + mac_lld_init(); +} + +/** + * @brief Initialize the standard part of a @p MACDriver structure. + * + * @param[in] macp pointer to the @p MACDriver object + */ +void macObjectInit(MACDriver *macp) { + + chSemInit(&macp->md_tdsem, 0); + chSemInit(&macp->md_rdsem, 0); +#if CH_USE_EVENTS + chEvtInit(&macp->md_rdevent); +#endif +} + +/** + * @brief MAC address setup. + * + * @param[in] macp pointer to the @p MACDriver object + * @param[in] p pointer to a six bytes buffer containing the MAC address. If + * this parameter is set to @p NULL then a system default MAC is + * used. + * + * @note This function must be invoked only with the driver in the stopped + * state. If invoked on an active interface then it is ignored. + */ +void macSetAddress(MACDriver *macp, const uint8_t *p) { + + mac_lld_set_address(macp, p); +} + +/** + * @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. + */ +msg_t macWaitTransmitDescriptor(MACDriver *macp, + MACTransmitDescriptor *tdp, + systime_t time) { + msg_t msg; + + while (((msg = max_lld_get_transmit_descriptor(macp, tdp)) != RDY_OK) && + (time > 0)) { + chSysLock(); + systime_t now = chTimeNow(); + if ((msg = chSemWaitTimeoutS(&macp->md_tdsem, time)) == RDY_TIMEOUT) + 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 + */ +void macReleaseTransmitDescriptor(MACTransmitDescriptor *tdp) { + + 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. + */ +msg_t macWaitReceiveDescriptor(MACDriver *macp, + MACReceiveDescriptor *rdp, + systime_t time) { + msg_t msg; + + while (((msg = max_lld_get_receive_descriptor(macp, rdp)) != RDY_OK) && + (time > 0)) { + chSysLock(); + systime_t now = chTimeNow(); + if ((msg = chSemWaitTimeoutS(&macp->md_rdsem, time)) == RDY_TIMEOUT) + 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 + */ +void macReleaseReceiveDescriptor(MACReceiveDescriptor *rdp) { + + 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. + */ +bool_t macPollLinkStatus(MACDriver *macp) { + + return mac_lld_poll_link_status(macp); +} + +/** @} */ diff --git a/os/io/src/mii.c b/os/io/src/mii.c new file mode 100644 index 000000000..da36db9d2 --- /dev/null +++ b/os/io/src/mii.c @@ -0,0 +1,37 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 mii.c + * @brief mii Driver code. + * @addtogroup MII + * @{ + */ + +#include +#include +#include + +/* + * Currently there is no code, everything is done in the header, you may + * omit this file from the project but this may change in future releases. + * The file is here because the driver's naming pattern. + */ + +/** @} */ diff --git a/os/io/src/mmc_spi.c b/os/io/src/mmc_spi.c new file mode 100644 index 000000000..4f6adaf7d --- /dev/null +++ b/os/io/src/mmc_spi.c @@ -0,0 +1,572 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 mmc_spi.c + * @brief MMC over SPI driver code + * @addtogroup MMC_SPI + * @{ + */ + +#include +#include +#include + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +void tmrfunc(void *p) { + MMCDriver *mmcp = p; + + if (mmcp->mmc_cnt > 0) { + if (mmcp->mmc_is_inserted()) { + if (--mmcp->mmc_cnt == 0) { + mmcp->mmc_state = MMC_INSERTED; + chEvtBroadcastI(&mmcp->mmc_inserted_event); + } + } + else + mmcp->mmc_cnt = MMC_POLLING_INTERVAL; + } + else { + if (!mmcp->mmc_is_inserted()) { + mmcp->mmc_state = MMC_WAIT; + mmcp->mmc_cnt = MMC_POLLING_INTERVAL; + chEvtBroadcastI(&mmcp->mmc_removed_event); + } + } + chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp); +} + +/** + * @brief Waits an idle condition. + * + * @param[in] mmcp pointer to the @p MMCDriver object + */ +static void wait(MMCDriver *mmcp) { + int i; + uint8_t buf[4]; + + for (i = 0; i < 16; i++) { + spiReceive(mmcp->mmc_spip, 1, buf); + if (buf[0] == 0xFF) + break; + } + /* Looks like it is a long wait.*/ + while (TRUE) { + spiReceive(mmcp->mmc_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 cmd[in] the command id + * @param arg[in] the command argument + */ +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; + buf[5] = 0x95; /* Valid for CMD0 ignored by other commands. */ + spiSend(mmcp->mmc_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. + */ +static uint8_t recvr1(MMCDriver *mmcp) { + int i; + uint8_t r1[1]; + + for (i = 0; i < 9; i++) { + spiReceive(mmcp->mmc_spip, 1, r1); + if (r1[0] != 0xFF) + return r1[0]; + } + return 0xFF; +} + +/** + * @brief Sends a command an returns a single byte response. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param cmd[in] the command id + * @param arg[in] the command argument + * + * @return The response as an @p uint8_t value. + * @retval 0xFF timed out. + */ +static uint8_t send_command(MMCDriver *mmcp, uint8_t cmd, uint32_t arg) { + uint8_t r1; + + spiSelect(mmcp->mmc_spip); + send_hdr(mmcp, cmd, arg); + r1 = recvr1(mmcp); + spiUnselect(mmcp->mmc_spip); + return r1; +} + +/** + * @brief Waits that the card reaches an idle state. + * + * @param[in] mmcp pointer to the @p MMCDriver object + */ +static void sync(MMCDriver *mmcp) { + uint8_t buf[1]; + + spiSelect(mmcp->mmc_spip); + while (TRUE) { + spiReceive(mmcp->mmc_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->mmc_spip); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief MMC over SPI driver initialization. + */ +void mmcInit(void) { + +} + +/** + * @brief Initializes an instance. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * @param[in] spip pointer to the SPI driver to be used as interface + * @param[in] lscfg low speed configuration for the SPI driver + * @param[in] hscfg high speed configuration for the SPI driver + * @param[in] is_protected function that returns the card write protection + * setting + * @param[in] is_inserted function that returns the card insertion sensor + * status + */ +void mmcObjectInit(MMCDriver *mmcp, SPIDriver *spip, + const SPIConfig *lscfg, const SPIConfig *hscfg, + mmcquery_t is_protected, mmcquery_t is_inserted) { + + mmcp->mmc_state = MMC_STOP; + mmcp->mmc_config = NULL; + mmcp->mmc_spip = spip; + mmcp->mmc_lscfg = lscfg; + mmcp->mmc_hscfg = hscfg; + mmcp->mmc_is_protected = is_protected; + mmcp->mmc_is_inserted = is_inserted; + chEvtInit(&mmcp->mmc_inserted_event); + chEvtInit(&mmcp->mmc_removed_event); +} + +/** + * @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 + */ +void mmcStart(MMCDriver *mmcp, const MMCConfig *config) { + + chDbgCheck((mmcp != NULL) && (config != NULL), "mmcStart"); + + chSysLock(); + chDbgAssert(mmcp->mmc_state == MMC_STOP, "mmcStart(), #1", "invalid state"); + mmcp->mmc_config = config; + mmcp->mmc_state = MMC_WAIT; + mmcp->mmc_cnt = MMC_POLLING_INTERVAL; + chVTSetI(&mmcp->mmc_vt, MS2ST(MMC_POLLING_DELAY), tmrfunc, mmcp); + chSysUnlock(); +} + +/** + * @brief Disables the MMC peripheral. + * + * @param[in] mmcp pointer to the @p MMCDriver object + */ +void mmcStop(MMCDriver *mmcp) { + + chDbgCheck(mmcp != NULL, "mmcStop"); + + chSysLock(); + chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && + (mmcp->mmc_state != MMC_READING) && + (mmcp->mmc_state != MMC_WRITING), + "mmcStop(), #1", + "invalid state"); + if (mmcp->mmc_state != MMC_STOP) { + mmcp->mmc_state = MMC_STOP; + chVTResetI(&mmcp->mmc_vt); + } + chSysUnlock(); + spiStop(mmcp->mmc_spip); +} + +/** + * @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 FALSE the operation was successful and the driver is now + * in the @p MMC_READY state. + * @retval TRUE the operation failed. + */ +bool_t mmcConnect(MMCDriver *mmcp) { + unsigned i; + bool_t result; + + chDbgCheck(mmcp != NULL, "mmcConnect"); + + chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && + (mmcp->mmc_state != MMC_STOP), + "mmcConnect(), #1", + "invalid state"); + + if (mmcp->mmc_state == MMC_INSERTED) { + /* Slow clock mode and 128 clock pulses.*/ + spiStart(mmcp->mmc_spip, mmcp->mmc_lscfg); + spiIgnore(mmcp->mmc_spip, 16); + + /* SPI mode selection.*/ + i = 0; + while (TRUE) { + if (send_command(mmcp, MMC_CMDGOIDLE, 0) == 0x01) + break; + if (++i >= MMC_CMD0_RETRY) + return TRUE; + chThdSleepMilliseconds(10); + } + + /* Initialization. */ + i = 0; + while (TRUE) { + uint8_t b = send_command(mmcp, MMC_CMDINIT, 0); + if (b == 0x00) + break; + if (b != 0x01) + return TRUE; + if (++i >= MMC_CMD1_RETRY) + return TRUE; + chThdSleepMilliseconds(10); + } + + /* Initialization complete, full speed. */ + spiStart(mmcp->mmc_spip, mmcp->mmc_hscfg); + + /* Setting block size.*/ + if (send_command(mmcp, MMC_CMDSETBLOCKLEN, MMC_SECTOR_SIZE) != 0x00) + return TRUE; + + /* Transition to MMC_READY state (if not extracted).*/ + chSysLock(); + if (mmcp->mmc_state == MMC_INSERTED) { + mmcp->mmc_state = MMC_READY; + result = FALSE; + } + else + result = TRUE; + chSysUnlock(); + return result; + } + if (mmcp->mmc_state == MMC_READY) + return FALSE; + /* Any other state is invalid.*/ + return TRUE; +} + +/** + * @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 FALSE the operation was successful and the driver is now + * in the @p MMC_INSERTED state. + * @retval TRUE the operation failed. + */ +bool_t mmcDisconnect(MMCDriver *mmcp) { + + chDbgCheck(mmcp != NULL, "mmcConnect"); + + chDbgAssert((mmcp->mmc_state != MMC_UNINIT) && + (mmcp->mmc_state != MMC_STOP), + "mmcDisconnect(), #1", + "invalid state"); + switch (mmcp->mmc_state) { + case MMC_READY: + /* Wait for the pending write operations to complete.*/ + sync(mmcp); + chSysLock(); + if (mmcp->mmc_state == MMC_READY) + mmcp->mmc_state = MMC_INSERTED; + chSysUnlock(); + case MMC_INSERTED: + return FALSE; + default: + return TRUE; + } +} + +/** + * @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 FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStartSequentialRead(MMCDriver *mmcp, uint32_t startblk) { + + chDbgCheck(mmcp != NULL, "mmcStartSequentialRead"); + + chSysLock(); + if (mmcp->mmc_state != MMC_READY) { + chSysUnlock(); + return TRUE; + } + mmcp->mmc_state = MMC_READING; + chSysUnlock(); + + spiSelect(mmcp->mmc_spip); + send_hdr(mmcp, MMC_CMDREADMULTIPLE, startblk * MMC_SECTOR_SIZE); + if (recvr1(mmcp) != 0x00) { + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_READING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; + } + return FALSE; +} + +/** + * @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 FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcSequentialRead(MMCDriver *mmcp, uint8_t *buffer) { + int i; + + chDbgCheck((mmcp != NULL) && (buffer != NULL), "mmcSequentialRead"); + + chSysLock(); + if (mmcp->mmc_state != MMC_READING) { + chSysUnlock(); + return TRUE; + } + chSysUnlock(); + + for (i = 0; i < MMC_WAIT_DATA; i++) { + spiReceive(mmcp->mmc_spip, 1, buffer); + if (buffer[0] == 0xFE) { + spiReceive(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer); + /* CRC ignored. */ + spiIgnore(mmcp->mmc_spip, 2); + return FALSE; + } + } + /* Timeout.*/ + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_READING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; +} + +/** + * @brief Stops a sequential read gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStopSequentialRead(MMCDriver *mmcp) { + static const uint8_t stopcmd[] = {0x40 | MMC_CMDSTOP, 0, 0, 0, 0, 1, 0xFF}; + bool_t result; + + chDbgCheck(mmcp != NULL, "mmcStopSequentialRead"); + + chSysLock(); + if (mmcp->mmc_state != MMC_READING) { + chSysUnlock(); + return TRUE; + } + chSysUnlock(); + + spiSend(mmcp->mmc_spip, sizeof(stopcmd), stopcmd); + result = recvr1(mmcp) != 0x00; + spiUnselect(mmcp->mmc_spip); + + chSysLock(); + if (mmcp->mmc_state == MMC_READING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return result; +} + +/** + * @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 FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStartSequentialWrite(MMCDriver *mmcp, uint32_t startblk) { + + chDbgCheck(mmcp != NULL, "mmcStartSequentialWrite"); + + chSysLock(); + if (mmcp->mmc_state != MMC_READY) { + chSysUnlock(); + return TRUE; + } + mmcp->mmc_state = MMC_WRITING; + chSysUnlock(); + + spiSelect(mmcp->mmc_spip); + send_hdr(mmcp, MMC_CMDWRITEMULTIPLE, startblk * MMC_SECTOR_SIZE); + if (recvr1(mmcp) != 0x00) { + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_WRITING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; + } + return FALSE; +} + +/** + * @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 FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +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), "mmcSequentialRead"); + + chSysLock(); + if (mmcp->mmc_state != MMC_WRITING) { + chSysUnlock(); + return TRUE; + } + chSysUnlock(); + + spiSend(mmcp->mmc_spip, sizeof(start), start); /* Data prologue. */ + spiSend(mmcp->mmc_spip, MMC_SECTOR_SIZE, buffer); /* Data. */ + spiIgnore(mmcp->mmc_spip, 2); /* CRC ignored. */ + spiReceive(mmcp->mmc_spip, 1, b); + if ((b[0] & 0x1F) == 0x05) + return FALSE; + + /* Error.*/ + spiUnselect(mmcp->mmc_spip); + chSysLock(); + if (mmcp->mmc_state == MMC_WRITING) + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return TRUE; +} + +/** + * @brief Stops a sequential write gracefully. + * + * @param[in] mmcp pointer to the @p MMCDriver object + * + * @return The operation status. + * @retval FALSE the operation was successful. + * @retval TRUE the operation failed. + */ +bool_t mmcStopSequentialWrite(MMCDriver *mmcp) { + static const uint8_t stop[] = {0xFD, 0xFF}; + + chDbgCheck(mmcp != NULL, "mmcStopSequentialWrite"); + + chSysLock(); + if (mmcp->mmc_state != MMC_WRITING) { + chSysUnlock(); + return TRUE; + } + chSysUnlock(); + + spiSend(mmcp->mmc_spip, sizeof(stop), stop); + spiUnselect(mmcp->mmc_spip); + + chSysLock(); + if (mmcp->mmc_state == MMC_WRITING) { + mmcp->mmc_state = MMC_READY; + chSysUnlock(); + return FALSE; + } + chSysUnlock(); + return TRUE; +} + +/** @} */ diff --git a/os/io/src/pal.c b/os/io/src/pal.c new file mode 100644 index 000000000..f7645f621 --- /dev/null +++ b/os/io/src/pal.c @@ -0,0 +1,94 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/** + * @brief Read from an I/O bus. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @return The bus logical states. + * + * @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. + */ +ioportmask_t palReadBus(IOBus *bus) { + + chDbgCheck((bus != NULL) && + (bus->bus_offset > PAL_IOPORTS_WIDTH), "palReadBus"); + + return palReadGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset); +} + +/** + * @brief Write to an I/O bus. + * + * @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. + * + * @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. + */ +void palWriteBus(IOBus *bus, ioportmask_t bits) { + + chDbgCheck((bus != NULL) && + (bus->bus_offset > PAL_IOPORTS_WIDTH), "palWriteBus"); + + palWriteGroup(bus->bus_portid, bus->bus_mask, bus->bus_offset, bits); +} + +/** + * @brief Programs a bus with the specified mode. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] mode the 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. + */ +void palSetBusMode(IOBus *bus, uint_fast8_t mode) { + + chDbgCheck((bus != NULL) && + (bus->bus_offset > PAL_IOPORTS_WIDTH), "palSetBusMode"); + + palSetGroupMode(bus->bus_portid, bus->bus_mask, mode); +} + +/** @} */ diff --git a/os/io/src/serial.c b/os/io/src/serial.c new file mode 100644 index 000000000..9c398f5f0 --- /dev/null +++ b/os/io/src/serial.c @@ -0,0 +1,197 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/* + * Interface implementation, the following functions just invoke the equivalent + * queue-level function or macro. + */ +static bool_t putwouldblock(void *ip) { + + return chOQIsFull(&((SerialDriver *)ip)->d2.oqueue); +} + +static bool_t getwouldblock(void *ip) { + + return chIQIsEmpty(&((SerialDriver *)ip)->d2.iqueue); +} + +static msg_t put(void *ip, uint8_t b, systime_t timeout) { + + return chOQPutTimeout(&((SerialDriver *)ip)->d2.oqueue, b, timeout); +} + +static msg_t get(void *ip, systime_t timeout) { + + return chIQGetTimeout(&((SerialDriver *)ip)->d2.iqueue, timeout); +} + +static size_t write(void *ip, uint8_t *buffer, size_t n) { + + return chOQWrite(&((SerialDriver *)ip)->d2.oqueue, buffer, n); +} + +static size_t read(void *ip, uint8_t *buffer, size_t n) { + + return chIQRead(&((SerialDriver *)ip)->d2.iqueue, buffer, n); +} + +static const struct SerialDriverVMT vmt = { + {putwouldblock, getwouldblock, put, get}, + {write, read}, + {} +}; + +/** + * @brief Serial Driver initialization. + */ +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. + */ +void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { + + sdp->vmt = &vmt; + chEvtInit(&sdp->d1.ievent); + chEvtInit(&sdp->d1.oevent); + chEvtInit(&sdp->d2.sevent); + sdp->d2.flags = SD_NO_ERROR; + chIQInit(&sdp->d2.iqueue, sdp->d2.ib, SERIAL_BUFFERS_SIZE, inotify); + chOQInit(&sdp->d2.oqueue, sdp->d2.ob, SERIAL_BUFFERS_SIZE, onotify); +} + +/** + * @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. + */ +void sdStart(SerialDriver *sdp, const SerialDriverConfig *config) { + + chSysLock(); + sd_lld_start(sdp, config); + 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 SerialDrive object + */ +void sdStop(SerialDriver *sdp) { + + chSysLock(); + sd_lld_stop(sdp); + chOQResetI(&sdp->d2.oqueue); + chIQResetI(&sdp->d2.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. + * @param[in] sd pointer to a @p SerialDriver structure + * @param[in] b the byte to be written in the driver's Input Queue + */ +void sdIncomingDataI(SerialDriver *sd, uint8_t b) { + + if (chIQPutI(&sd->d2.iqueue, b) < Q_OK) + sdAddFlagsI(sd, SD_OVERRUN_ERROR); + else + chEvtBroadcastI(&sd->d1.ievent); +} + +/** + * @brief Handles outgoing data. + * @details Must be called from the output interrupt service routine in order + * to get the next byte to be transmitted. + * + * @param[in] sd 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). + */ +msg_t sdRequestDataI(SerialDriver *sd) { + + msg_t b = chOQGetI(&sd->d2.oqueue); + if (b < Q_OK) + chEvtBroadcastI(&sd->d1.oevent); + return b; +} + +/** + * @brief Handles communication events/errors. + * @details Must be called from the I/O interrupt service routine in order to + * notify I/O conditions as errors, signals change etc. + * + * @param[in] sd pointer to a @p SerialDriver structure + * @param[in] mask condition flags to be added to the mask + */ +void sdAddFlagsI(SerialDriver *sd, sdflags_t mask) { + + sd->d2.flags |= mask; + chEvtBroadcastI(&sd->d2.sevent); +} + +/** + * @brief Returns and clears the errors mask associated to the driver. + * + * @param[in] sd pointer to a @p SerialDriver structure + * @return The condition flags modified since last time this function was + * invoked. + */ +sdflags_t sdGetAndClearFlags(SerialDriver *sd) { + sdflags_t mask; + + mask = sd->d2.flags; + sd->d2.flags = SD_NO_ERROR; + return mask; +} + +/** @} */ diff --git a/os/io/src/spi.c b/os/io/src/spi.c new file mode 100644 index 000000000..4d45d217d --- /dev/null +++ b/os/io/src/spi.c @@ -0,0 +1,258 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 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 +#include + +/** + * @brief SPI Driver initialization. + */ +void spiInit(void) { + + spi_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p SPIDriver structure. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spiObjectInit(SPIDriver *spip) { + + spip->spd_state = SPI_STOP; +#if CH_USE_MUTEXES + chMtxInit(&spip->spd_mutex); +#elif CH_USE_SEMAPHORES + chSemInit(&spip->spd_semaphore, 1); +#endif + spip->spd_config = NULL; +} + +/** + * @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 + */ +void spiStart(SPIDriver *spip, const SPIConfig *config) { + + chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); + + chSysLock(); + chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), + "spiStart(), #1", + "invalid state"); + spip->spd_config = config; + spi_lld_start(spip); + spip->spd_state = SPI_READY; + chSysUnlock(); +} + +/** + * @brief Deactivates the SPI peripheral. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spiStop(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiStop"); + + chSysLock(); + chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), + "spiStop(), #1", + "invalid state"); + spi_lld_stop(spip); + spip->spd_state = SPI_STOP; + chSysUnlock(); +} + +/** + * @brief Asserts the slave select signal and prepares for transfers. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spiSelect(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiSelect"); + + chSysLock(); + chDbgAssert((spip->spd_state == SPI_READY) || + (spip->spd_state == SPI_ACTIVE), + "spiSelect(), #1", + "not idle"); + spi_lld_select(spip); + spip->spd_state = SPI_ACTIVE; + chSysUnlock(); +} + +/** + * @brief Deasserts the slave select signal. + * @details The previously selected peripheral is unselected. + * + * @param[in] spip pointer to the @p SPIDriver object + */ +void spiUnselect(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiUnselect"); + + chSysLock(); + chDbgAssert((spip->spd_state == SPI_READY) || + (spip->spd_state == SPI_ACTIVE), + "spiUnselect(), #1", + "not locked"); + spi_lld_unselect(spip); + spip->spd_state = SPI_READY; + chSysUnlock(); +} + +/** + * @brief Ignores data on the SPI bus. + * @details This function transmits a series of idle words on the SPI bus and + * ignores the received data. This function can be invoked even + * when a slave select signal has not been yet asserted. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] n number of words to be ignored + */ +void spiIgnore(SPIDriver *spip, size_t n) { + + chDbgCheck((spip != NULL) && (n > 0), "spiIgnore"); + chDbgAssert((spip->spd_state == SPI_READY) || (spip->spd_state == SPI_ACTIVE), + "spiIgnore(), #1", + "not active"); + + spi_lld_ignore(spip, n); +} + +/** + * @brief Exchanges data on the SPI bus. + * @details This function performs a simultaneous transmit/receive operation. + * + * @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 + * + * @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. + */ +void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { + + chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), + "spiExchange"); + chDbgAssert(spip->spd_state == SPI_ACTIVE, + "spiExchange(), #1", + "not active"); + + spi_lld_exchange(spip, n, txbuf, rxbuf); +} + +/** + * @brief Sends data ever the SPI bus. + * + * @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 + * + * @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. + */ +void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { + + chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), + "spiSend"); + chDbgAssert(spip->spd_state == SPI_ACTIVE, + "spiSend(), #1", + "not active"); + + spi_lld_send(spip, n, txbuf); +} + +/** + * @brief Receives data from the SPI bus. + * + * @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 + * + * @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. + */ +void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { + + chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), + "spiReceive"); + chDbgAssert(spip->spd_state == SPI_ACTIVE, + "spiReceive(), #1", + "not active"); + + spi_lld_receive(spip, n, rxbuf); +} + +#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. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. + */ +void spiAcquireBus(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiAcquireBus"); + +#if CH_USE_MUTEXES + chMtxLock(&spip->spd_mutex); +#elif CH_USE_SEMAPHORES + chSemWait(&spip->spd_semaphore); +#endif +} + +/** + * @brief Releases exclusive access to the SPI bus. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION + * option is set to @p TRUE. + */ +void spiReleaseBus(SPIDriver *spip) { + + chDbgCheck(spip != NULL, "spiReleaseBus"); + +#if CH_USE_MUTEXES + (void)spip; + chMtxUnlock(); +#elif CH_USE_SEMAPHORES + chSemSignal(&spip->spd_semaphore); +#endif +} +#endif /*SPI_USE_MUTUAL_EXCLUSION */ + +/** @} */ -- cgit v1.2.3