ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 /** 00028 * @file spi.c 00029 * @brief SPI Driver code. 00030 * 00031 * @addtogroup SPI 00032 * @{ 00033 */ 00034 00035 #include "ch.h" 00036 #include "hal.h" 00037 00038 #if CH_HAL_USE_SPI || defined(__DOXYGEN__) 00039 00040 /*===========================================================================*/ 00041 /* Driver exported variables. */ 00042 /*===========================================================================*/ 00043 00044 /*===========================================================================*/ 00045 /* Driver local variables. */ 00046 /*===========================================================================*/ 00047 00048 /*===========================================================================*/ 00049 /* Driver local functions. */ 00050 /*===========================================================================*/ 00051 00052 /*===========================================================================*/ 00053 /* Driver exported functions. */ 00054 /*===========================================================================*/ 00055 00056 /** 00057 * @brief SPI Driver initialization. 00058 */ 00059 void spiInit(void) { 00060 00061 spi_lld_init(); 00062 } 00063 00064 /** 00065 * @brief Initializes the standard part of a @p SPIDriver structure. 00066 * 00067 * @param[in] spip pointer to the @p SPIDriver object 00068 */ 00069 void spiObjectInit(SPIDriver *spip) { 00070 00071 spip->spd_state = SPI_STOP; 00072 #if CH_USE_MUTEXES 00073 chMtxInit(&spip->spd_mutex); 00074 #elif CH_USE_SEMAPHORES 00075 chSemInit(&spip->spd_semaphore, 1); 00076 #endif 00077 spip->spd_config = NULL; 00078 } 00079 00080 /** 00081 * @brief Configures and activates the SPI peripheral. 00082 * 00083 * @param[in] spip pointer to the @p SPIDriver object 00084 * @param[in] config pointer to the @p SPIConfig object 00085 */ 00086 void spiStart(SPIDriver *spip, const SPIConfig *config) { 00087 00088 chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); 00089 00090 chSysLock(); 00091 chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), 00092 "spiStart(), #1", 00093 "invalid state"); 00094 spip->spd_config = config; 00095 spi_lld_start(spip); 00096 spip->spd_state = SPI_READY; 00097 chSysUnlock(); 00098 } 00099 00100 /** 00101 * @brief Deactivates the SPI peripheral. 00102 * 00103 * @param[in] spip pointer to the @p SPIDriver object 00104 */ 00105 void spiStop(SPIDriver *spip) { 00106 00107 chDbgCheck(spip != NULL, "spiStop"); 00108 00109 chSysLock(); 00110 chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), 00111 "spiStop(), #1", 00112 "invalid state"); 00113 spi_lld_stop(spip); 00114 spip->spd_state = SPI_STOP; 00115 chSysUnlock(); 00116 } 00117 00118 /** 00119 * @brief Asserts the slave select signal and prepares for transfers. 00120 * 00121 * @param[in] spip pointer to the @p SPIDriver object 00122 */ 00123 void spiSelect(SPIDriver *spip) { 00124 00125 chDbgCheck(spip != NULL, "spiSelect"); 00126 00127 chSysLock(); 00128 chDbgAssert((spip->spd_state == SPI_READY) || 00129 (spip->spd_state == SPI_ACTIVE), 00130 "spiSelect(), #1", 00131 "not idle"); 00132 spi_lld_select(spip); 00133 spip->spd_state = SPI_ACTIVE; 00134 chSysUnlock(); 00135 } 00136 00137 /** 00138 * @brief Deasserts the slave select signal. 00139 * @details The previously selected peripheral is unselected. 00140 * 00141 * @param[in] spip pointer to the @p SPIDriver object 00142 */ 00143 void spiUnselect(SPIDriver *spip) { 00144 00145 chDbgCheck(spip != NULL, "spiUnselect"); 00146 00147 chSysLock(); 00148 chDbgAssert((spip->spd_state == SPI_READY) || 00149 (spip->spd_state == SPI_ACTIVE), 00150 "spiUnselect(), #1", 00151 "not locked"); 00152 spi_lld_unselect(spip); 00153 spip->spd_state = SPI_READY; 00154 chSysUnlock(); 00155 } 00156 00157 /** 00158 * @brief Ignores data on the SPI bus. 00159 * @details This function transmits a series of idle words on the SPI bus and 00160 * ignores the received data. This function can be invoked even 00161 * when a slave select signal has not been yet asserted. 00162 * 00163 * @param[in] spip pointer to the @p SPIDriver object 00164 * @param[in] n number of words to be ignored 00165 */ 00166 void spiIgnore(SPIDriver *spip, size_t n) { 00167 00168 chDbgCheck((spip != NULL) && (n > 0), "spiIgnore"); 00169 chDbgAssert((spip->spd_state == SPI_READY) || (spip->spd_state == SPI_ACTIVE), 00170 "spiIgnore(), #1", 00171 "not active"); 00172 00173 spi_lld_ignore(spip, n); 00174 } 00175 00176 /** 00177 * @brief Exchanges data on the SPI bus. 00178 * @details This function performs a simultaneous transmit/receive operation. 00179 * @note The buffers are organized as uint8_t arrays for data sizes below 00180 * or equal to 8 bits else it is organized as uint16_t arrays. 00181 * 00182 * @param[in] spip pointer to the @p SPIDriver object 00183 * @param[in] n number of words to be exchanged 00184 * @param[in] txbuf the pointer to the transmit buffer 00185 * @param[out] rxbuf the pointer to the receive buffer 00186 */ 00187 void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { 00188 00189 chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), 00190 "spiExchange"); 00191 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00192 "spiExchange(), #1", 00193 "not active"); 00194 00195 spi_lld_exchange(spip, n, txbuf, rxbuf); 00196 } 00197 00198 /** 00199 * @brief Sends data ever the SPI bus. 00200 * @note The buffers are organized as uint8_t arrays for data sizes below 00201 * or equal to 8 bits else it is organized as uint16_t arrays. 00202 * 00203 * @param[in] spip pointer to the @p SPIDriver object 00204 * @param[in] n number of words to send 00205 * @param[in] txbuf the pointer to the transmit buffer 00206 */ 00207 void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { 00208 00209 chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), 00210 "spiSend"); 00211 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00212 "spiSend(), #1", 00213 "not active"); 00214 00215 spi_lld_send(spip, n, txbuf); 00216 } 00217 00218 /** 00219 * @brief Receives data from the SPI bus. 00220 * @note The buffers are organized as uint8_t arrays for data sizes below 00221 * or equal to 8 bits else it is organized as uint16_t arrays. 00222 * 00223 * @param[in] spip pointer to the @p SPIDriver object 00224 * @param[in] n number of words to receive 00225 * @param[out] rxbuf the pointer to the receive buffer 00226 */ 00227 void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { 00228 00229 chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), 00230 "spiReceive"); 00231 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00232 "spiReceive(), #1", 00233 "not active"); 00234 00235 spi_lld_receive(spip, n, rxbuf); 00236 } 00237 00238 #if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) 00239 /** 00240 * @brief Gains exclusive access to the SPI bus. 00241 * @details This function tries to gain ownership to the SPI bus, if the bus 00242 * is already being used then the invoking thread is queued. 00243 * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION 00244 * option is set to @p TRUE. 00245 * 00246 * @param[in] spip pointer to the @p SPIDriver object 00247 * 00248 */ 00249 void spiAcquireBus(SPIDriver *spip) { 00250 00251 chDbgCheck(spip != NULL, "spiAcquireBus"); 00252 00253 #if CH_USE_MUTEXES 00254 chMtxLock(&spip->spd_mutex); 00255 #elif CH_USE_SEMAPHORES 00256 chSemWait(&spip->spd_semaphore); 00257 #endif 00258 } 00259 00260 /** 00261 * @brief Releases exclusive access to the SPI bus. 00262 * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION 00263 * option is set to @p TRUE. 00264 * 00265 * @param[in] spip pointer to the @p SPIDriver object 00266 */ 00267 void spiReleaseBus(SPIDriver *spip) { 00268 00269 chDbgCheck(spip != NULL, "spiReleaseBus"); 00270 00271 #if CH_USE_MUTEXES 00272 (void)spip; 00273 chMtxUnlock(); 00274 #elif CH_USE_SEMAPHORES 00275 chSemSignal(&spip->spd_semaphore); 00276 #endif 00277 } 00278 #endif /* SPI_USE_MUTUAL_EXCLUSION */ 00279 00280 #endif /* CH_HAL_USE_SPI */ 00281 00282 /** @} */