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 SPI_USE_MUTUAL_EXCLUSION 00073 #if CH_USE_MUTEXES 00074 chMtxInit(&spip->spd_mutex); 00075 #else 00076 chSemInit(&spip->spd_semaphore, 1); 00077 #endif 00078 #endif /* SPI_USE_MUTUAL_EXCLUSION */ 00079 spip->spd_config = NULL; 00080 } 00081 00082 /** 00083 * @brief Configures and activates the SPI peripheral. 00084 * 00085 * @param[in] spip pointer to the @p SPIDriver object 00086 * @param[in] config pointer to the @p SPIConfig object 00087 */ 00088 void spiStart(SPIDriver *spip, const SPIConfig *config) { 00089 00090 chDbgCheck((spip != NULL) && (config != NULL), "spiStart"); 00091 00092 chSysLock(); 00093 chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), 00094 "spiStart(), #1", 00095 "invalid state"); 00096 spip->spd_config = config; 00097 spi_lld_start(spip); 00098 spip->spd_state = SPI_READY; 00099 chSysUnlock(); 00100 } 00101 00102 /** 00103 * @brief Deactivates the SPI peripheral. 00104 * 00105 * @param[in] spip pointer to the @p SPIDriver object 00106 */ 00107 void spiStop(SPIDriver *spip) { 00108 00109 chDbgCheck(spip != NULL, "spiStop"); 00110 00111 chSysLock(); 00112 chDbgAssert((spip->spd_state == SPI_STOP) || (spip->spd_state == SPI_READY), 00113 "spiStop(), #1", 00114 "invalid state"); 00115 spi_lld_stop(spip); 00116 spip->spd_state = SPI_STOP; 00117 chSysUnlock(); 00118 } 00119 00120 /** 00121 * @brief Asserts the slave select signal and prepares for transfers. 00122 * 00123 * @param[in] spip pointer to the @p SPIDriver object 00124 */ 00125 void spiSelect(SPIDriver *spip) { 00126 00127 chDbgCheck(spip != NULL, "spiSelect"); 00128 00129 chSysLock(); 00130 chDbgAssert((spip->spd_state == SPI_READY) || 00131 (spip->spd_state == SPI_ACTIVE), 00132 "spiSelect(), #1", 00133 "not idle"); 00134 spi_lld_select(spip); 00135 spip->spd_state = SPI_ACTIVE; 00136 chSysUnlock(); 00137 } 00138 00139 /** 00140 * @brief Deasserts the slave select signal. 00141 * @details The previously selected peripheral is unselected. 00142 * 00143 * @param[in] spip pointer to the @p SPIDriver object 00144 */ 00145 void spiUnselect(SPIDriver *spip) { 00146 00147 chDbgCheck(spip != NULL, "spiUnselect"); 00148 00149 chSysLock(); 00150 chDbgAssert((spip->spd_state == SPI_READY) || 00151 (spip->spd_state == SPI_ACTIVE), 00152 "spiUnselect(), #1", 00153 "not locked"); 00154 spi_lld_unselect(spip); 00155 spip->spd_state = SPI_READY; 00156 chSysUnlock(); 00157 } 00158 00159 /** 00160 * @brief Ignores data on the SPI bus. 00161 * @details This function transmits a series of idle words on the SPI bus and 00162 * ignores the received data. This function can be invoked even 00163 * when a slave select signal has not been yet asserted. 00164 * 00165 * @param[in] spip pointer to the @p SPIDriver object 00166 * @param[in] n number of words to be ignored 00167 */ 00168 void spiIgnore(SPIDriver *spip, size_t n) { 00169 00170 chDbgCheck((spip != NULL) && (n > 0), "spiIgnore"); 00171 chDbgAssert((spip->spd_state == SPI_READY) || (spip->spd_state == SPI_ACTIVE), 00172 "spiIgnore(), #1", 00173 "not active"); 00174 00175 spi_lld_ignore(spip, n); 00176 } 00177 00178 /** 00179 * @brief Exchanges data on the SPI bus. 00180 * @details This function performs a simultaneous transmit/receive operation. 00181 * @note The buffers are organized as uint8_t arrays for data sizes below 00182 * or equal to 8 bits else it is organized as uint16_t arrays. 00183 * 00184 * @param[in] spip pointer to the @p SPIDriver object 00185 * @param[in] n number of words to be exchanged 00186 * @param[in] txbuf the pointer to the transmit buffer 00187 * @param[out] rxbuf the pointer to the receive buffer 00188 */ 00189 void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { 00190 00191 chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL) && (txbuf != NULL), 00192 "spiExchange"); 00193 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00194 "spiExchange(), #1", 00195 "not active"); 00196 00197 spi_lld_exchange(spip, n, txbuf, rxbuf); 00198 } 00199 00200 /** 00201 * @brief Sends data over the SPI bus. 00202 * @note The buffers are organized as uint8_t arrays for data sizes below 00203 * or equal to 8 bits else it is organized as uint16_t arrays. 00204 * 00205 * @param[in] spip pointer to the @p SPIDriver object 00206 * @param[in] n number of words to send 00207 * @param[in] txbuf the pointer to the transmit buffer 00208 */ 00209 void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { 00210 00211 chDbgCheck((spip != NULL) && (n > 0) && (txbuf != NULL), 00212 "spiSend"); 00213 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00214 "spiSend(), #1", 00215 "not active"); 00216 00217 spi_lld_send(spip, n, txbuf); 00218 } 00219 00220 /** 00221 * @brief Receives data from the SPI bus. 00222 * @note The buffers are organized as uint8_t arrays for data sizes below 00223 * or equal to 8 bits else it is organized as uint16_t arrays. 00224 * 00225 * @param[in] spip pointer to the @p SPIDriver object 00226 * @param[in] n number of words to receive 00227 * @param[out] rxbuf the pointer to the receive buffer 00228 */ 00229 void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { 00230 00231 chDbgCheck((spip != NULL) && (n > 0) && (rxbuf != NULL), 00232 "spiReceive"); 00233 chDbgAssert(spip->spd_state == SPI_ACTIVE, 00234 "spiReceive(), #1", 00235 "not active"); 00236 00237 spi_lld_receive(spip, n, rxbuf); 00238 } 00239 00240 #if SPI_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) 00241 /** 00242 * @brief Gains exclusive access to the SPI bus. 00243 * @details This function tries to gain ownership to the SPI bus, if the bus 00244 * is already being used then the invoking thread is queued. 00245 * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION 00246 * option is set to @p TRUE. 00247 * 00248 * @param[in] spip pointer to the @p SPIDriver object 00249 * 00250 */ 00251 void spiAcquireBus(SPIDriver *spip) { 00252 00253 chDbgCheck(spip != NULL, "spiAcquireBus"); 00254 00255 #if CH_USE_MUTEXES 00256 chMtxLock(&spip->spd_mutex); 00257 #elif CH_USE_SEMAPHORES 00258 chSemWait(&spip->spd_semaphore); 00259 #endif 00260 } 00261 00262 /** 00263 * @brief Releases exclusive access to the SPI bus. 00264 * @note This function is only available when the @p SPI_USE_MUTUAL_EXCLUSION 00265 * option is set to @p TRUE. 00266 * 00267 * @param[in] spip pointer to the @p SPIDriver object 00268 */ 00269 void spiReleaseBus(SPIDriver *spip) { 00270 00271 chDbgCheck(spip != NULL, "spiReleaseBus"); 00272 00273 #if CH_USE_MUTEXES 00274 (void)spip; 00275 chMtxUnlock(); 00276 #elif CH_USE_SEMAPHORES 00277 chSemSignal(&spip->spd_semaphore); 00278 #endif 00279 } 00280 #endif /* SPI_USE_MUTUAL_EXCLUSION */ 00281 00282 #endif /* CH_HAL_USE_SPI */ 00283 00284 /** @} */