spi_bitbang.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /****************************************************************************
  2. * drivers/spi/spi_bitbang.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <stdlib.h>
  25. #include <assert.h>
  26. #include <errno.h>
  27. #include <debug.h>
  28. #include <nuttx/kmalloc.h>
  29. #include <nuttx/spi/spi.h>
  30. #include <nuttx/spi/spi_bitbang.h>
  31. #include <nuttx/semaphore.h>
  32. #ifdef CONFIG_SPI_BITBANG
  33. /****************************************************************************
  34. * Pre-processor Definitions
  35. ****************************************************************************/
  36. /* This file holds the static, device-independent portion of the generic
  37. * SPI-bit-bang driver. The full driver consists of 5 files:
  38. *
  39. * 1. drivers/spi/spi_bitbang.c: This file. This file holds the basic
  40. * SPI driver framework and not perform any direct bit-bang operations.
  41. * Rather, it will could out to board-specific logic to perform the
  42. * low level data transfers.
  43. * 2. include/nuttx/spi/spi_bitbang.h: This header file provides the
  44. * data types and function prototypes needed to utilize the logic in
  45. * this file.
  46. * 3. boards/<arch>/<chip>/<board>/src/<file>: The implementation of the
  47. * low-level bit-bang logic resides in some file in the board source
  48. * directory. This board-specific logic includes the bit-bang skeleton
  49. * logic provided in include/nuttx/spi/spi_bitbang.c.
  50. * 4. include/nuttx/spi/spi_bitbang.c. Despite the .c extension, this is
  51. * really an included file. It is used in this way: 1) The board-
  52. * specific logic in boards/<arch>/<chip>/<board>/src/<file> provides
  53. * some definitions then 2) includes include/nuttx/spi/spi_bitbang.c.
  54. * That file will then use those definitions to implement the low-level
  55. * bit-bang logic. The board-specific logic then calls
  56. * spi_create_bitbang() in this file to instantiate the complete SPI
  57. * driver.
  58. *
  59. * See include/nuttx/spi/spi_bitbang.c for more detailed usage
  60. * information.
  61. */
  62. /****************************************************************************
  63. * Private Function Prototypes
  64. ****************************************************************************/
  65. /* SPI methods */
  66. static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
  67. static void spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
  68. bool selected);
  69. static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
  70. uint32_t frequency);
  71. static void spi_setmode(FAR struct spi_dev_s *dev,
  72. enum spi_mode_e mode);
  73. static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
  74. static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
  75. static void spi_exchange(FAR struct spi_dev_s *dev,
  76. FAR const void *txbuffer, FAR void *rxbuffer,
  77. size_t nwords);
  78. #ifndef CONFIG_SPI_EXCHANGE
  79. static void spi_sndblock(FAR struct spi_dev_s *dev,
  80. FAR const void *buffer, size_t nwords);
  81. static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
  82. size_t nwords);
  83. #endif
  84. static uint8_t spi_status(FAR struct spi_dev_s *dev, uint32_t devid);
  85. #ifdef CONFIG_SPI_CMDDATA
  86. static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
  87. bool cmd);
  88. #endif
  89. /****************************************************************************
  90. * Private Data
  91. ****************************************************************************/
  92. /* SPI driver operations */
  93. static const struct spi_ops_s g_spiops =
  94. {
  95. spi_lock, /* lock */
  96. spi_select, /* select */
  97. spi_setfrequency, /* setfrequency */
  98. spi_setmode, /* setmode */
  99. spi_setbits, /* setbits */
  100. #ifdef CONFIG_SPI_HWFEATURES
  101. 0, /* hwfeatures */
  102. #endif
  103. spi_status, /* status */
  104. #ifdef CONFIG_SPI_CMDDATA
  105. spi_cmddata, /* cmddata */
  106. #endif
  107. spi_send, /* send */
  108. #ifdef CONFIG_SPI_EXCHANGE
  109. spi_exchange, /* exchange */
  110. #else
  111. spi_sndblock, /* sndblock */
  112. spi_recvblock, /* recvblock */
  113. #endif
  114. 0 /* registercallback */
  115. };
  116. /****************************************************************************
  117. * Private Functions
  118. ****************************************************************************/
  119. /****************************************************************************
  120. * Name: spi_lock
  121. *
  122. * Description:
  123. * On SPI buses where there are multiple devices, it will be necessary to
  124. * lock SPI to have exclusive access to the buses for a sequence of
  125. * transfers. The bus should be locked before the chip is selected. After
  126. * locking the SPI bus, the caller should then also call the setfrequency,
  127. * setbits, and setmode methods to make sure that the SPI is properly
  128. * configured for the device. If the SPI bus is being shared, then it
  129. * may have been left in an incompatible state.
  130. *
  131. * Input Parameters:
  132. * dev - Device-specific state data
  133. * lock - true: Lock spi bus, false: unlock SPI bus
  134. *
  135. * Returned Value:
  136. * None
  137. *
  138. ****************************************************************************/
  139. static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
  140. {
  141. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  142. int ret;
  143. spiinfo("lock=%d\n", lock);
  144. if (lock)
  145. {
  146. ret = nxsem_wait_uninterruptible(&priv->exclsem);
  147. }
  148. else
  149. {
  150. ret = nxsem_post(&priv->exclsem);
  151. }
  152. return ret;
  153. }
  154. /****************************************************************************
  155. * Name: spi_select
  156. *
  157. * Description:
  158. * Set/clear the chip select line for the selected device.
  159. *
  160. * Input Parameters:
  161. * dev - Device-specific state data
  162. * devid - Identifies the device to be selected
  163. * selected - select or de-select device
  164. *
  165. * Returned Value:
  166. * None
  167. *
  168. ****************************************************************************/
  169. static void spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
  170. bool selected)
  171. {
  172. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  173. spiinfo("devid=%d selected=%d\n", devid, selected);
  174. DEBUGASSERT(priv && priv->low->select);
  175. priv->low->select(priv, devid, selected);
  176. }
  177. /****************************************************************************
  178. * Name: spi_setfrequency
  179. *
  180. * Description:
  181. * Set the SPI frequency.
  182. *
  183. * Input Parameters:
  184. * dev - Device-specific state data
  185. * frequency - The SPI frequency requested
  186. *
  187. * Returned Value:
  188. * Returns the actual frequency selected
  189. *
  190. ****************************************************************************/
  191. static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
  192. uint32_t frequency)
  193. {
  194. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  195. uint32_t actual;
  196. DEBUGASSERT(priv && priv->low->setfrequency);
  197. actual = priv->low->setfrequency(priv, frequency);
  198. spiinfo("frequency=%d holdtime=%d actual=%d\n",
  199. frequency, priv->holdtime, actual);
  200. return actual;
  201. }
  202. /****************************************************************************
  203. * Name: spi_setmode
  204. *
  205. * Description:
  206. * Set the SPI mode. Optional. See enum spi_mode_e for mode definitions
  207. *
  208. * Input Parameters:
  209. * dev - Device-specific state data
  210. * mode - The SPI mode requested
  211. *
  212. * Returned Value:
  213. * none
  214. *
  215. ****************************************************************************/
  216. static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
  217. {
  218. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  219. DEBUGASSERT(priv && priv->low->setmode);
  220. priv->low->setmode(priv, mode);
  221. spiinfo("mode=%d exchange=%p\n", mode, priv->exchange);
  222. }
  223. /****************************************************************************
  224. * Name: spi_setbits
  225. *
  226. * Description:
  227. * Set the number if bits per word.
  228. *
  229. * Input Parameters:
  230. * dev - Device-specific state data
  231. * nbits - The number of bits requests
  232. *
  233. * Returned Value:
  234. * none
  235. *
  236. ****************************************************************************/
  237. static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
  238. {
  239. #ifdef CONFIG_SPI_BITBANG_VARWIDTH
  240. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  241. spiinfo("nbits=%d\n", nbits);
  242. DEBUGASSERT(priv && nbits > 0 && nbits <= 16);
  243. priv->nbits = nbits;
  244. #else
  245. spiinfo("nbits=%d\n", nbits);
  246. DEBUGASSERT(nbits == 8);
  247. #endif
  248. }
  249. /****************************************************************************
  250. * Name: spi_send
  251. *
  252. * Description:
  253. * Exchange one word on SPI
  254. *
  255. * Input Parameters:
  256. * dev - Device-specific state data
  257. * wd - The word to send. the size of the data is determined by the
  258. * number of bits selected for the SPI interface.
  259. *
  260. * Returned Value:
  261. * response
  262. *
  263. ****************************************************************************/
  264. static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
  265. {
  266. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  267. DEBUGASSERT(priv && priv->low && priv->low->exchange);
  268. return priv->low->exchange(priv, (uint16_t)wd);
  269. }
  270. /****************************************************************************
  271. * Name: spi_exchange
  272. *
  273. * Description:
  274. * Exahange a block of data from SPI. Required.
  275. *
  276. * Input Parameters:
  277. * dev - Device-specific state data
  278. * txbuffer - A pointer to the buffer of data to be sent
  279. * rxbuffer - A pointer to the buffer in which to receive data
  280. * nwords - the length of data that to be exchanged in units of words.
  281. * The wordsize is determined by the number of bits-per-word
  282. * selected for the SPI interface. If nbits <= 8, the data is
  283. * packed into uint8_t's; if nbits >8, the data is packed into
  284. * uint16_t's
  285. *
  286. * Returned Value:
  287. * None
  288. *
  289. ****************************************************************************/
  290. static void spi_exchange(FAR struct spi_dev_s *dev,
  291. FAR const void *txbuffer, FAR void *rxbuffer,
  292. size_t nwords)
  293. {
  294. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  295. FAR const uint8_t *src = (FAR const uint8_t *)txbuffer;
  296. FAR uint8_t *dest = (FAR uint8_t *)rxbuffer;
  297. uint16_t dataout;
  298. uint16_t datain;
  299. spiinfo("txbuffer=%p rxbuffer=%p nwords=%d\n", txbuffer, rxbuffer, nwords);
  300. DEBUGASSERT(priv && priv->low && priv->low->exchange);
  301. /* If there is no data source, send 0xff */
  302. if (!src)
  303. {
  304. dataout = 0xff;
  305. }
  306. /* Exchange each word */
  307. while (nwords-- > 0)
  308. {
  309. /* If there is source data, get the next word from the source */
  310. if (src)
  311. {
  312. dataout = (uint16_t)*src++;
  313. #ifdef CONFIG_SPI_BITBANG_VARWIDTH
  314. if (priv->nbits > 8)
  315. {
  316. #ifdef CONFIG_ENDIAN_BIG
  317. dataout <<= 8;
  318. dataout |= *src++;
  319. #else
  320. dataout |= (uint16_t)(*src++) << 8;
  321. #endif
  322. }
  323. #endif
  324. }
  325. /* Exchange the word of data */
  326. datain = priv->low->exchange(priv, dataout);
  327. /* If there is a data sink, transfer the data to the receive buffer */
  328. if (dest)
  329. {
  330. #ifdef CONFIG_SPI_BITBANG_VARWIDTH
  331. if (priv->nbits > 8)
  332. {
  333. #ifdef CONFIG_ENDIAN_BIG
  334. *dest++ = (uint8_t)(datain >> 8);
  335. *dest++ = (uint8_t)datain;
  336. #else
  337. *dest++ = (uint8_t)datain;
  338. *dest++ = (uint8_t)(datain >> 8);
  339. #endif
  340. }
  341. #else
  342. *dest++ = (uint8_t)datain;
  343. #endif
  344. }
  345. }
  346. }
  347. /****************************************************************************
  348. * Name: spi_sndblock
  349. *
  350. * Description:
  351. * Send a block of data on SPI
  352. *
  353. * Input Parameters:
  354. * dev - Device-specific state data
  355. * buffer - A pointer to the buffer of data to be sent
  356. * nwords - the length of data to send from the buffer in number of words.
  357. * The wordsize is determined by the number of bits-per-word
  358. * selected for the SPI interface. If nbits <= 8, the data is
  359. * packed into uint8_t's; if nbits >8, the data is packed into
  360. * uint16_t's
  361. *
  362. * Returned Value:
  363. * None
  364. *
  365. ****************************************************************************/
  366. #ifndef CONFIG_SPI_EXCHANGE
  367. static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
  368. size_t nwords)
  369. {
  370. /* spi_exchange can do this. */
  371. spi_exchange(dev, buffer, NULL, nwords);
  372. }
  373. #endif
  374. /****************************************************************************
  375. * Name: spi_recvblock
  376. *
  377. * Description:
  378. * Revice a block of data from SPI
  379. *
  380. * Input Parameters:
  381. * dev - Device-specific state data
  382. * buffer - A pointer to the buffer in which to receive data
  383. * nwords - the length of data that can be received in the buffer in number
  384. * of words. The wordsize is determined by the number of
  385. * bits-per-word selected for the SPI interface. If nbits <= 8,
  386. * the data is packed into uint8_t's; if nbits >8, the data is
  387. * packed into uint16_t's
  388. *
  389. * Returned Value:
  390. * None
  391. *
  392. ****************************************************************************/
  393. #ifndef CONFIG_SPI_EXCHANGE
  394. static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
  395. size_t nwords)
  396. {
  397. /* spi_exchange can do this. */
  398. spi_exchange(dev, NULL, buffer, nwords);
  399. }
  400. #endif
  401. /****************************************************************************
  402. * Name: spi_status
  403. *
  404. * Description:
  405. * Get status bits associated with the device associated with 'devid'
  406. *
  407. * Input Parameters:
  408. * dev - Device-specific state data
  409. * devid - Identifies the device of interest
  410. *
  411. * Returned Value:
  412. * Bit encoded status byte
  413. *
  414. ****************************************************************************/
  415. static uint8_t spi_status(FAR struct spi_dev_s *dev, uint32_t devid)
  416. {
  417. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  418. DEBUGASSERT(priv && priv->low && priv->low->status);
  419. return priv->low->status(priv, devid);
  420. }
  421. /****************************************************************************
  422. * Name: spi_cmddata
  423. *
  424. * Description:
  425. * Control the SPI CMD/DATA like for the device associated with 'devid'
  426. *
  427. * Input Parameters:
  428. * dev - Device-specific state data
  429. * devid - Identifies the device of interest
  430. * cmd - True:CMD False:DATA
  431. *
  432. * Returned Value:
  433. * OK on success; a negated errno value on failure
  434. *
  435. ****************************************************************************/
  436. #ifdef CONFIG_SPI_CMDDATA
  437. static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
  438. bool cmd)
  439. {
  440. FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
  441. DEBUGASSERT(priv && priv->low && priv->low->status);
  442. return priv->low->cmddata(priv, devid, cmd);
  443. }
  444. #endif
  445. /****************************************************************************
  446. * Public Functions
  447. ****************************************************************************/
  448. /****************************************************************************
  449. * Name: spi_create_bitbang
  450. *
  451. * Description:
  452. * Create an instance of the SPI bit-bang driver.
  453. *
  454. ****************************************************************************/
  455. FAR struct spi_dev_s *spi_create_bitbang(FAR const struct
  456. spi_bitbang_ops_s *low)
  457. {
  458. FAR struct spi_bitbang_s *priv;
  459. DEBUGASSERT(low);
  460. /* Allocate an instance of the SPI bit bang structure */
  461. priv = (FAR struct spi_bitbang_s *)
  462. kmm_zalloc(sizeof(struct spi_bitbang_s));
  463. if (!priv)
  464. {
  465. spierr("ERROR: Failed to allocate the device structure\n");
  466. return NULL;
  467. }
  468. /* Initialize the driver structure */
  469. priv->dev.ops = &g_spiops;
  470. priv->low = low;
  471. #ifdef CONFIG_SPI_BITBANG_VARWIDTH
  472. priv->nbits = 8;
  473. #endif
  474. nxsem_init(&priv->exclsem, 0, 1);
  475. /* Select an initial state of mode 0, 8-bits, and 400KHz */
  476. low->setmode(priv, SPIDEV_MODE0);
  477. low->setfrequency(priv, 400000);
  478. /* And return the initialized driver structure */
  479. return &priv->dev;
  480. }
  481. #endif /* CONFIG_SPI_BITBANG */