ssi.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097
  1. //*****************************************************************************
  2. //
  3. // ssi.c - Driver for Synchronous Serial Interface.
  4. //
  5. // Copyright (c) 2005-2017 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions
  10. // are met:
  11. //
  12. // Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. //
  15. // Redistributions in binary form must reproduce the above copyright
  16. // notice, this list of conditions and the following disclaimer in the
  17. // documentation and/or other materials provided with the
  18. // distribution.
  19. //
  20. // Neither the name of Texas Instruments Incorporated nor the names of
  21. // its contributors may be used to endorse or promote products derived
  22. // from this software without specific prior written permission.
  23. //
  24. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  25. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  26. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  27. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  28. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  29. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  30. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  31. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  32. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  33. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  34. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //*****************************************************************************
  37. //*****************************************************************************
  38. //
  39. //! \addtogroup ssi_api
  40. //! @{
  41. //
  42. //*****************************************************************************
  43. #include <ti/devices/msp432e4/inc/msp432e411y.h>
  44. #include "types.h"
  45. #include <stdbool.h>
  46. #include <stdint.h>
  47. #include "inc/hw_ssi.h"
  48. #include "inc/hw_sysctl.h"
  49. #include "debug.h"
  50. #include "interrupt.h"
  51. #include "ssi.h"
  52. //*****************************************************************************
  53. //
  54. // A mapping of timer base address to interrupt number.
  55. //
  56. //*****************************************************************************
  57. static const uint32_t g_ppui32SSIIntMap[][2] =
  58. {
  59. { SSI0_BASE, INT_SSI0 },
  60. { SSI1_BASE, INT_SSI1 },
  61. { SSI2_BASE, INT_SSI2 },
  62. { SSI3_BASE, INT_SSI3 },
  63. };
  64. static const uint_fast8_t g_ui8SSIIntMapRows =
  65. sizeof(g_ppui32SSIIntMap) / sizeof(g_ppui32SSIIntMap[0]);
  66. //*****************************************************************************
  67. //
  68. //! \internal
  69. //! Checks an SSI base address.
  70. //!
  71. //! \param ui32Base specifies the SSI module base address.
  72. //!
  73. //! This function determines if a SSI module base address is valid.
  74. //!
  75. //! \return Returns \b true if the base address is valid and \b false
  76. //! otherwise.
  77. //
  78. //*****************************************************************************
  79. #ifdef DEBUG
  80. static bool
  81. _SSIBaseValid(uint32_t ui32Base)
  82. {
  83. return ((ui32Base == SSI0_BASE) || (ui32Base == SSI1_BASE) ||
  84. (ui32Base == SSI2_BASE) || (ui32Base == SSI3_BASE));
  85. }
  86. #endif
  87. //*****************************************************************************
  88. //
  89. //! Returns the interrupt number of SSI module .
  90. //!
  91. //! \param ui32Base is the base address of the SSI module.
  92. //!
  93. //! This function returns the interrupt number for the SSI module with the base
  94. //! address passed in the \e ui32Base parameter.
  95. //!
  96. //! \return Returns an SSI interrupt number, or 0 if the interrupt does not
  97. //! exist.
  98. //
  99. //*****************************************************************************
  100. static uint32_t
  101. _SSIIntNumberGet(uint32_t ui32Base)
  102. {
  103. uint_fast8_t ui8Idx, ui8Rows;
  104. const uint32_t (*ppui32SSIIntMap)[2];
  105. //
  106. // Check the arguments.
  107. //
  108. ASSERT(_SSIBaseValid(ui32Base));
  109. ppui32SSIIntMap = g_ppui32SSIIntMap;
  110. ui8Rows = g_ui8SSIIntMapRows;
  111. //
  112. // Loop through the table that maps SSI base addresses to interrupt
  113. // numbers.
  114. //
  115. for (ui8Idx = 0; ui8Idx < ui8Rows; ui8Idx++)
  116. {
  117. //
  118. // See if this base address matches.
  119. //
  120. if (ppui32SSIIntMap[ui8Idx][0] == ui32Base)
  121. {
  122. //
  123. // Return the corresponding interrupt number.
  124. //
  125. return (ppui32SSIIntMap[ui8Idx][1]);
  126. }
  127. }
  128. //
  129. // The base address could not be found, so return an error.
  130. //
  131. return (0);
  132. }
  133. //*****************************************************************************
  134. //
  135. //! Configures the synchronous serial interface.
  136. //!
  137. //! \param ui32Base specifies the SSI module base address.
  138. //! \param ui32SSIClk is the rate of the clock supplied to the SSI module.
  139. //! \param ui32Protocol specifies the data transfer protocol.
  140. //! \param ui32Mode specifies the mode of operation.
  141. //! \param ui32BitRate specifies the clock rate.
  142. //! \param ui32DataWidth specifies number of bits transferred per frame.
  143. //!
  144. //! This function configures the synchronous serial interface. It sets
  145. //! the SSI protocol, mode of operation, bit rate, and data width.
  146. //!
  147. //! The \e ui32Protocol parameter defines the data frame format. The
  148. //! \e ui32Protocol parameter can be one of the following values:
  149. //! \b SSI_FRF_MOTO_MODE_0, \b SSI_FRF_MOTO_MODE_1, \b SSI_FRF_MOTO_MODE_2,
  150. //! \b SSI_FRF_MOTO_MODE_3, or \b SSI_FRF_TI.
  151. //! The Motorola frame formats encode the following
  152. //! polarity and phase configurations:
  153. //!
  154. //! <pre>
  155. //! Polarity Phase Mode
  156. //! 0 0 SSI_FRF_MOTO_MODE_0
  157. //! 0 1 SSI_FRF_MOTO_MODE_1
  158. //! 1 0 SSI_FRF_MOTO_MODE_2
  159. //! 1 1 SSI_FRF_MOTO_MODE_3
  160. //! </pre>
  161. //!
  162. //! The \e ui32Mode parameter defines the operating mode of the SSI module.
  163. //! The SSI module can operate as a master or slave; if it is a slave, the SSI
  164. //! can be configured to disable output on its serial output line. The
  165. //! \e ui32Mode parameter can be one of the following values:
  166. //! \b SSI_MODE_MASTER, or \b SSI_MODE_SLAVE.
  167. //!
  168. //! The \e ui32BitRate parameter defines the bit rate for the SSI. This bit
  169. //! rate must satisfy the following clock ratio criteria:
  170. //!
  171. //! - FSSI >= 2 * bit rate (master mode)
  172. //! - FSSI >= 12 * bit rate (slave modes)
  173. //!
  174. //! where FSSI is the frequency of the clock supplied to the SSI module.
  175. //!
  176. //! The \e ui32DataWidth parameter defines the width of the data transfers and
  177. //! can be a value between 4 and 16, inclusive.
  178. //!
  179. //! The peripheral clock is the same as the processor clock. The frequency of
  180. //! the system clock is the value returned by SysCtlClockFreqSet(),
  181. //! or it can be explicitly hard coded if it is constant and known (to save the
  182. //! code/execution overhead of fetch of the variable call holding the return
  183. //! value of SysCtlClockFreqSet()).
  184. //!
  185. //! \return None.
  186. //
  187. //*****************************************************************************
  188. void
  189. SSIConfigSetExpClk(uint32_t ui32Base, uint32_t ui32SSIClk,
  190. uint32_t ui32Protocol, uint32_t ui32Mode,
  191. uint32_t ui32BitRate, uint32_t ui32DataWidth)
  192. {
  193. uint32_t ui32MaxBitRate;
  194. uint32_t ui32RegVal;
  195. uint32_t ui32PreDiv;
  196. uint32_t ui32SCR;
  197. uint32_t ui32SPH_SPO;
  198. //
  199. // Check the arguments.
  200. //
  201. ASSERT(_SSIBaseValid(ui32Base));
  202. ASSERT((ui32Protocol == SSI_FRF_MOTO_MODE_0) ||
  203. (ui32Protocol == SSI_FRF_MOTO_MODE_1) ||
  204. (ui32Protocol == SSI_FRF_MOTO_MODE_2) ||
  205. (ui32Protocol == SSI_FRF_MOTO_MODE_3) ||
  206. (ui32Protocol == SSI_FRF_TI));
  207. ASSERT((ui32Mode == SSI_MODE_MASTER) ||
  208. (ui32Mode == SSI_MODE_SLAVE));
  209. ASSERT(((ui32Mode == SSI_MODE_MASTER) &&
  210. (ui32BitRate <= (ui32SSIClk / 2))) ||
  211. ((ui32Mode != SSI_MODE_MASTER) &&
  212. (ui32BitRate <= (ui32SSIClk / 12))));
  213. ASSERT((ui32SSIClk / ui32BitRate) <= (254 * 256));
  214. ASSERT((ui32DataWidth >= 4) && (ui32DataWidth <= 16));
  215. //
  216. // Set the mode.
  217. //
  218. ui32RegVal = (ui32Mode == SSI_MODE_MASTER) ? 0 : SSI_CR1_MS;
  219. HWREG(ui32Base + SSI_O_CR1) = ui32RegVal;
  220. //
  221. // Set the clock predivider.
  222. //
  223. ui32MaxBitRate = ui32SSIClk / ui32BitRate;
  224. ui32PreDiv = 0;
  225. do
  226. {
  227. ui32PreDiv += 2;
  228. ui32SCR = (ui32MaxBitRate / ui32PreDiv) - 1;
  229. }
  230. while (ui32SCR > 255);
  231. HWREG(ui32Base + SSI_O_CPSR) = ui32PreDiv;
  232. //
  233. // Set protocol and clock rate.
  234. //
  235. ui32SPH_SPO = (ui32Protocol & 3) << 6;
  236. ui32Protocol &= SSI_CR0_FRF_M;
  237. ui32RegVal = (ui32SCR << 8) | ui32SPH_SPO | ui32Protocol |
  238. (ui32DataWidth - 1);
  239. HWREG(ui32Base + SSI_O_CR0) = ui32RegVal;
  240. }
  241. //*****************************************************************************
  242. //
  243. //! Enables the synchronous serial interface.
  244. //!
  245. //! \param ui32Base specifies the SSI module base address.
  246. //!
  247. //! This function enables operation of the synchronous serial interface. The
  248. //! synchronous serial interface must be configured before it is enabled.
  249. //!
  250. //! \return None.
  251. //
  252. //*****************************************************************************
  253. void
  254. SSIEnable(uint32_t ui32Base)
  255. {
  256. //
  257. // Check the arguments.
  258. //
  259. ASSERT(_SSIBaseValid(ui32Base));
  260. //
  261. // Read-modify-write the enable bit.
  262. //
  263. HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_SSE;
  264. }
  265. //*****************************************************************************
  266. //
  267. //! Disables the synchronous serial interface.
  268. //!
  269. //! \param ui32Base specifies the SSI module base address.
  270. //!
  271. //! This function disables operation of the synchronous serial interface.
  272. //!
  273. //! \return None.
  274. //
  275. //*****************************************************************************
  276. void
  277. SSIDisable(uint32_t ui32Base)
  278. {
  279. //
  280. // Check the arguments.
  281. //
  282. ASSERT(_SSIBaseValid(ui32Base));
  283. //
  284. // Read-modify-write the enable bit.
  285. //
  286. HWREG(ui32Base + SSI_O_CR1) &= ~(SSI_CR1_SSE);
  287. }
  288. //*****************************************************************************
  289. //
  290. //! Registers an interrupt handler for the synchronous serial interface.
  291. //!
  292. //! \param ui32Base specifies the SSI module base address.
  293. //! \param pfnHandler is a pointer to the function to be called when the
  294. //! synchronous serial interface interrupt occurs.
  295. //!
  296. //! This function registers the handler to be called when an SSI interrupt
  297. //! occurs. This function enables the global interrupt in the interrupt
  298. //! controller; specific SSI interrupts must be enabled via SSIIntEnable(). If
  299. //! necessary, it is the interrupt handler's responsibility to clear the
  300. //! interrupt source via SSIIntClear().
  301. //!
  302. //! \sa IntRegister() for important information about registering interrupt
  303. //! handlers.
  304. //!
  305. //! \return None.
  306. //
  307. //*****************************************************************************
  308. void
  309. SSIIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
  310. {
  311. uint32_t ui32Int;
  312. //
  313. // Check the arguments.
  314. //
  315. ASSERT(_SSIBaseValid(ui32Base));
  316. //
  317. // Determine the interrupt number based on the SSI module.
  318. //
  319. ui32Int = _SSIIntNumberGet(ui32Base);
  320. ASSERT(ui32Int != 0);
  321. //
  322. // Register the interrupt handler, returning an error if an error occurs.
  323. //
  324. IntRegister(ui32Int, pfnHandler);
  325. //
  326. // Enable the synchronous serial interface interrupt.
  327. //
  328. IntEnable(ui32Int);
  329. }
  330. //*****************************************************************************
  331. //
  332. //! Unregisters an interrupt handler for the synchronous serial interface.
  333. //!
  334. //! \param ui32Base specifies the SSI module base address.
  335. //!
  336. //! This function clears the handler to be called when an SSI interrupt
  337. //! occurs. This function also masks off the interrupt in the interrupt
  338. //! controller so that the interrupt handler no longer is called.
  339. //!
  340. //! \sa IntRegister() for important information about registering interrupt
  341. //! handlers.
  342. //!
  343. //! \return None.
  344. //
  345. //*****************************************************************************
  346. void
  347. SSIIntUnregister(uint32_t ui32Base)
  348. {
  349. uint32_t ui32Int;
  350. //
  351. // Check the arguments.
  352. //
  353. ASSERT(_SSIBaseValid(ui32Base));
  354. //
  355. // Determine the interrupt number based on the SSI module.
  356. //
  357. ui32Int = _SSIIntNumberGet(ui32Base);
  358. ASSERT(ui32Int != 0);
  359. //
  360. // Disable the interrupt.
  361. //
  362. IntDisable(ui32Int);
  363. //
  364. // Unregister the interrupt handler.
  365. //
  366. IntUnregister(ui32Int);
  367. }
  368. //*****************************************************************************
  369. //
  370. //! Enables individual SSI interrupt sources.
  371. //!
  372. //! \param ui32Base specifies the SSI module base address.
  373. //! \param ui32IntFlags is a bit mask of the interrupt sources to be enabled.
  374. //!
  375. //! This function enables the indicated SSI interrupt sources. Only the
  376. //! sources that are enabled can be reflected to the processor interrupt;
  377. //! disabled sources have no effect on the processor. The \e ui32IntFlags
  378. //! parameter can be any of the \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, or
  379. //! \b SSI_RXOR values.
  380. //!
  381. //! \return None.
  382. //
  383. //*****************************************************************************
  384. void
  385. SSIIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
  386. {
  387. //
  388. // Check the arguments.
  389. //
  390. ASSERT(_SSIBaseValid(ui32Base));
  391. //
  392. // Enable the specified interrupts.
  393. //
  394. HWREG(ui32Base + SSI_O_IM) |= ui32IntFlags;
  395. }
  396. //*****************************************************************************
  397. //
  398. //! Disables individual SSI interrupt sources.
  399. //!
  400. //! \param ui32Base specifies the SSI module base address.
  401. //! \param ui32IntFlags is a bit mask of the interrupt sources to be disabled.
  402. //!
  403. //! This function disables the indicated SSI interrupt sources. The
  404. //! \e ui32IntFlags parameter can be any of the \b SSI_TXFF, \b SSI_RXFF,
  405. //! \b SSI_RXTO, or \b SSI_RXOR values.
  406. //!
  407. //! \return None.
  408. //
  409. //*****************************************************************************
  410. void
  411. SSIIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
  412. {
  413. //
  414. // Check the arguments.
  415. //
  416. ASSERT(_SSIBaseValid(ui32Base));
  417. //
  418. // Disable the specified interrupts.
  419. //
  420. HWREG(ui32Base + SSI_O_IM) &= ~(ui32IntFlags);
  421. }
  422. //*****************************************************************************
  423. //
  424. //! Gets the current interrupt status.
  425. //!
  426. //! \param ui32Base specifies the SSI module base address.
  427. //! \param bMasked is \b false if the raw interrupt status is required or
  428. //! \b true if the masked interrupt status is required.
  429. //!
  430. //! This function returns the interrupt status for the SSI module. Either the
  431. //! raw interrupt status or the status of interrupts that are allowed to
  432. //! reflect to the processor can be returned.
  433. //!
  434. //! \return The current interrupt status, enumerated as a bit field of
  435. //! \b SSI_TXFF, \b SSI_RXFF, \b SSI_RXTO, and \b SSI_RXOR.
  436. //
  437. //*****************************************************************************
  438. uint32_t
  439. SSIIntStatus(uint32_t ui32Base, bool bMasked)
  440. {
  441. //
  442. // Check the arguments.
  443. //
  444. ASSERT(_SSIBaseValid(ui32Base));
  445. //
  446. // Return either the interrupt status or the raw interrupt status as
  447. // requested.
  448. //
  449. if (bMasked)
  450. {
  451. return (HWREG(ui32Base + SSI_O_MIS));
  452. }
  453. else
  454. {
  455. return (HWREG(ui32Base + SSI_O_RIS));
  456. }
  457. }
  458. //*****************************************************************************
  459. //
  460. //! Clears SSI interrupt sources.
  461. //!
  462. //! \param ui32Base specifies the SSI module base address.
  463. //! \param ui32IntFlags is a bit mask of the interrupt sources to be cleared.
  464. //!
  465. //! This function clears the specified SSI interrupt sources so that they no
  466. //! longer assert. This function must be called in the interrupt handler to
  467. //! keep the interrupts from being triggered again immediately upon exit. The
  468. //! \e ui32IntFlags parameter can consist of either or both the \b SSI_RXTO and
  469. //! \b SSI_RXOR values.
  470. //!
  471. //! \note Because there is a write buffer in the Cortex-M processor, it may
  472. //! take several clock cycles before the interrupt source is actually cleared.
  473. //! Therefore, it is recommended that the interrupt source be cleared early in
  474. //! the interrupt handler (as opposed to the very last action) to avoid
  475. //! returning from the interrupt handler before the interrupt source is
  476. //! actually cleared. Failure to do so may result in the interrupt handler
  477. //! being immediately reentered (because the interrupt controller still sees
  478. //! the interrupt source asserted).
  479. //!
  480. //! \return None.
  481. //
  482. //*****************************************************************************
  483. void
  484. SSIIntClear(uint32_t ui32Base, uint32_t ui32IntFlags)
  485. {
  486. //
  487. // Check the arguments.
  488. //
  489. ASSERT(_SSIBaseValid(ui32Base));
  490. //
  491. // Clear the requested interrupt sources.
  492. //
  493. HWREG(ui32Base + SSI_O_ICR) = ui32IntFlags;
  494. }
  495. //*****************************************************************************
  496. //
  497. //! Puts a data element into the SSI transmit FIFO.
  498. //!
  499. //! \param ui32Base specifies the SSI module base address.
  500. //! \param ui32Data is the data to be transmitted over the SSI interface.
  501. //!
  502. //! This function places the supplied data into the transmit FIFO of the
  503. //! specified SSI module. If there is no space available in the transmit FIFO,
  504. //! this function waits until there is space available before returning.
  505. //!
  506. //! \note The upper 32 - N bits of \e ui32Data are discarded by the hardware,
  507. //! where N is the data width as configured by SSIConfigSetExpClk(). For
  508. //! example, if the interface is configured for 8-bit data width, the upper 24
  509. //! bits of \e ui32Data are discarded.
  510. //!
  511. //! \return None.
  512. //
  513. //*****************************************************************************
  514. void
  515. SSIDataPut(uint32_t ui32Base, uint32_t ui32Data)
  516. {
  517. //
  518. // Check the arguments.
  519. //
  520. ASSERT(_SSIBaseValid(ui32Base));
  521. ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
  522. SSI_CR0_DSS_M))) == 0);
  523. //
  524. // Wait until there is space.
  525. //
  526. while (!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
  527. {
  528. }
  529. //
  530. // Write the data to the SSI.
  531. //
  532. HWREG(ui32Base + SSI_O_DR) = ui32Data;
  533. }
  534. //*****************************************************************************
  535. //
  536. //! Puts a data element into the SSI transmit FIFO.
  537. //!
  538. //! \param ui32Base specifies the SSI module base address.
  539. //! \param ui32Data is the data to be transmitted over the SSI interface.
  540. //!
  541. //! This function places the supplied data into the transmit FIFO of the
  542. //! specified SSI module. If there is no space in the FIFO, then this function
  543. //! returns a zero.
  544. //!
  545. //! \note The upper 32 - N bits of \e ui32Data are discarded by the hardware,
  546. //! where N is the data width as configured by SSIConfigSetExpClk(). For
  547. //! example, if the interface is configured for 8-bit data width, the upper 24
  548. //! bits of \e ui32Data are discarded.
  549. //!
  550. //! \return Returns the number of elements written to the SSI transmit FIFO.
  551. //
  552. //*****************************************************************************
  553. int32_t
  554. SSIDataPutNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
  555. {
  556. //
  557. // Check the arguments.
  558. //
  559. ASSERT(_SSIBaseValid(ui32Base));
  560. ASSERT((ui32Data & (0xfffffffe << (HWREG(ui32Base + SSI_O_CR0) &
  561. SSI_CR0_DSS_M))) == 0);
  562. //
  563. // Check for space to write.
  564. //
  565. if (HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
  566. {
  567. HWREG(ui32Base + SSI_O_DR) = ui32Data;
  568. return (1);
  569. }
  570. else
  571. {
  572. return (0);
  573. }
  574. }
  575. //*****************************************************************************
  576. //
  577. //! Gets a data element from the SSI receive FIFO.
  578. //!
  579. //! \param ui32Base specifies the SSI module base address.
  580. //! \param pui32Data is a pointer to a storage location for data that was
  581. //! received over the SSI interface.
  582. //!
  583. //! This function gets received data from the receive FIFO of the specified
  584. //! SSI module and places that data into the location specified by the
  585. //! \e pui32Data parameter. If there is no data available, this function waits
  586. //! until data is received before returning.
  587. //!
  588. //! \note Only the lower N bits of the value written to \e pui32Data contain
  589. //! valid data, where N is the data width as configured by
  590. //! SSIConfigSetExpClk(). For example, if the interface is configured for
  591. //! 8-bit data width, only the lower 8 bits of the value written to
  592. //! \e pui32Data contain valid data.
  593. //!
  594. //! \return None.
  595. //
  596. //*****************************************************************************
  597. void
  598. SSIDataGet(uint32_t ui32Base, uint32_t *pui32Data)
  599. {
  600. //
  601. // Check the arguments.
  602. //
  603. ASSERT(_SSIBaseValid(ui32Base));
  604. //
  605. // Wait until there is data to be read.
  606. //
  607. while (!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE))
  608. {
  609. }
  610. //
  611. // Read data from SSI.
  612. //
  613. *pui32Data = HWREG(ui32Base + SSI_O_DR);
  614. }
  615. //*****************************************************************************
  616. //
  617. //! Gets a data element from the SSI receive FIFO.
  618. //!
  619. //! \param ui32Base specifies the SSI module base address.
  620. //! \param pui32Data is a pointer to a storage location for data that was
  621. //! received over the SSI interface.
  622. //!
  623. //! This function gets received data from the receive FIFO of the specified SSI
  624. //! module and places that data into the location specified by the \e ui32Data
  625. //! parameter. If there is no data in the FIFO, then this function returns a
  626. //! zero.
  627. //!
  628. //! \note Only the lower N bits of the value written to \e pui32Data contain
  629. //! valid data, where N is the data width as configured by
  630. //! SSIConfigSetExpClk(). For example, if the interface is configured for
  631. //! 8-bit data width, only the lower 8 bits of the value written to
  632. //! \e pui32Data contain valid data.
  633. //!
  634. //! \return Returns the number of elements read from the SSI receive FIFO.
  635. //
  636. //*****************************************************************************
  637. int32_t
  638. SSIDataGetNonBlocking(uint32_t ui32Base, uint32_t *pui32Data)
  639. {
  640. //
  641. // Check the arguments.
  642. //
  643. ASSERT(_SSIBaseValid(ui32Base));
  644. //
  645. // Check for data to read.
  646. //
  647. if (HWREG(ui32Base + SSI_O_SR) & SSI_SR_RNE)
  648. {
  649. *pui32Data = HWREG(ui32Base + SSI_O_DR);
  650. return (1);
  651. }
  652. else
  653. {
  654. return (0);
  655. }
  656. }
  657. //*****************************************************************************
  658. //
  659. //! Enables SSI DMA operation.
  660. //!
  661. //! \param ui32Base is the base address of the SSI module.
  662. //! \param ui32DMAFlags is a bit mask of the DMA features to enable.
  663. //!
  664. //! This function enables the specified SSI DMA features. The SSI can be
  665. //! configured to use DMA for transmit and/or receive data transfers.
  666. //! The \e ui32DMAFlags parameter is the logical OR of any of the following
  667. //! values:
  668. //!
  669. //! - SSI_DMA_RX - enable DMA for receive
  670. //! - SSI_DMA_TX - enable DMA for transmit
  671. //!
  672. //! \note The uDMA controller must also be set up before DMA can be used
  673. //! with the SSI.
  674. //!
  675. //! \return None.
  676. //
  677. //*****************************************************************************
  678. void
  679. SSIDMAEnable(uint32_t ui32Base, uint32_t ui32DMAFlags)
  680. {
  681. //
  682. // Check the arguments.
  683. //
  684. ASSERT(_SSIBaseValid(ui32Base));
  685. //
  686. // Set the requested bits in the SSI DMA control register.
  687. //
  688. HWREG(ui32Base + SSI_O_DMACTL) |= ui32DMAFlags;
  689. }
  690. //*****************************************************************************
  691. //
  692. //! Disables SSI DMA operation.
  693. //!
  694. //! \param ui32Base is the base address of the SSI module.
  695. //! \param ui32DMAFlags is a bit mask of the DMA features to disable.
  696. //!
  697. //! This function is used to disable SSI DMA features that were enabled
  698. //! by SSIDMAEnable(). The specified SSI DMA features are disabled. The
  699. //! \e ui32DMAFlags parameter is the logical OR of any of the following values:
  700. //!
  701. //! - SSI_DMA_RX - disable DMA for receive
  702. //! - SSI_DMA_TX - disable DMA for transmit
  703. //!
  704. //! \return None.
  705. //
  706. //*****************************************************************************
  707. void
  708. SSIDMADisable(uint32_t ui32Base, uint32_t ui32DMAFlags)
  709. {
  710. //
  711. // Check the arguments.
  712. //
  713. ASSERT(_SSIBaseValid(ui32Base));
  714. //
  715. // Clear the requested bits in the SSI DMA control register.
  716. //
  717. HWREG(ui32Base + SSI_O_DMACTL) &= ~ui32DMAFlags;
  718. }
  719. //*****************************************************************************
  720. //
  721. //! Determines whether the SSI transmitter is busy or not.
  722. //!
  723. //! \param ui32Base is the base address of the SSI module.
  724. //!
  725. //! This function allows the caller to determine whether all transmitted bytes
  726. //! have cleared the transmitter hardware. If \b false is returned, then the
  727. //! transmit FIFO is empty and all bits of the last transmitted word have left
  728. //! the hardware shift register.
  729. //!
  730. //! \return Returns \b true if the SSI is transmitting or \b false if all
  731. //! transmissions are complete.
  732. //
  733. //*****************************************************************************
  734. bool
  735. SSIBusy(uint32_t ui32Base)
  736. {
  737. //
  738. // Check the arguments.
  739. //
  740. ASSERT(_SSIBaseValid(ui32Base));
  741. //
  742. // Determine if the SSI is busy.
  743. //
  744. return ((HWREG(ui32Base + SSI_O_SR) & SSI_SR_BSY) ? true : false);
  745. }
  746. //*****************************************************************************
  747. //
  748. //! Sets the data clock source for the specified SSI peripheral.
  749. //!
  750. //! \param ui32Base is the base address of the SSI module.
  751. //! \param ui32Source is the baud clock source for the SSI.
  752. //!
  753. //! This function allows the baud clock source for the SSI to be selected.
  754. //! The possible clock source are the system clock (\b SSI_CLOCK_SYSTEM) or
  755. //! the alternate clock (\b SSI_CLOCK_ALTCLK).
  756. //!
  757. //! Changing the baud clock source changes the data rate generated by the
  758. //! SSI. Therefore, the data rate should be reconfigured after any change to
  759. //! the SSI clock source.
  760. //!
  761. //! \return None.
  762. //
  763. //*****************************************************************************
  764. void
  765. SSIClockSourceSet(uint32_t ui32Base, uint32_t ui32Source)
  766. {
  767. //
  768. // Check the arguments.
  769. //
  770. ASSERT(_SSIBaseValid(ui32Base));
  771. ASSERT((ui32Source == SSI_CLOCK_SYSTEM) ||
  772. (ui32Source == SSI_CLOCK_ALTCLK));
  773. //
  774. // Set the SSI clock source.
  775. //
  776. HWREG(ui32Base + SSI_O_CC) = ui32Source;
  777. }
  778. //*****************************************************************************
  779. //
  780. //! Gets the data clock source for the specified SSI peripheral.
  781. //!
  782. //! \param ui32Base is the base address of the SSI module.
  783. //!
  784. //! This function returns the data clock source for the specified SSI.
  785. //!
  786. //! \return Returns the current clock source, which is either
  787. //! \b SSI_CLOCK_SYSTEM or \b SSI_CLOCK_ALTCLK.
  788. //
  789. //*****************************************************************************
  790. uint32_t
  791. SSIClockSourceGet(uint32_t ui32Base)
  792. {
  793. //
  794. // Check the arguments.
  795. //
  796. ASSERT(_SSIBaseValid(ui32Base));
  797. //
  798. // Return the SSI clock source.
  799. //
  800. return (HWREG(ui32Base + SSI_O_CC));
  801. }
  802. //*****************************************************************************
  803. //
  804. //! Selects the advanced mode of operation for the SSI module.
  805. //!
  806. //! \param ui32Base is the base address of the SSI module.
  807. //! \param ui32Mode is the mode of operation to use.
  808. //!
  809. //! This function selects the mode of operation for the SSI module, which is
  810. //! needed when using the advanced operation modes (Bi- or Quad-SPI). One of
  811. //! the following modes can be selected:
  812. //!
  813. //! - \b SSI_ADV_MODE_LEGACY - Disables the advanced modes of operation,
  814. //! resulting in legacy, or backwards-compatible, operation. When this mode
  815. //! is selected, it is not valid to switch to Bi- or Quad-SPI operation.
  816. //! This mode is the default.
  817. //! - \b SSI_ADV_MODE_WRITE - The advanced mode of operation where data is only
  818. //! written to the slave; any data clocked in via the \b SSIRx pin is thrown
  819. //! away (instead of being placed into the SSI Rx FIFO).
  820. //! - \b SSI_ADV_MODE_READ_WRITE - The advanced mode of operation where data is
  821. //! written to and read from the slave; this mode is the same as
  822. //! \b SSI_ADV_MODE_LEGACY but allows transitions to Bi- or Quad-SPI
  823. //! operation.
  824. //! - \b SSI_ADV_MODE_BI_READ - The advanced mode of operation where data is
  825. //! read from the slave in Bi-SPI mode, with two bits of data read on every
  826. //! SSI clock.
  827. //! - \b SSI_ADV_MODE_BI_WRITE - The advanced mode of operation where data is
  828. //! written to the slave in Bi-SPI mode, with two bits of data written on
  829. //! every SSI clock.
  830. //! - \b SSI_ADV_MODE_QUAD_READ - The advanced mode of operation where data is
  831. //! read from the slave in Quad-SPI mode, with four bits of data read on
  832. //! every SSI clock.
  833. //! - \b SSI_ADV_MODE_QUAD_WRITE - The advanced mode of operation where data is
  834. //! written to the slave in Quad-SPI mode, with four bits of data written on
  835. //! every SSI clock.
  836. //!
  837. //! The following mode transitions are valid (other transitions produce
  838. //! undefined results):
  839. //!
  840. //! \verbatim
  841. //! +----------+-------------------------------------------------------------+
  842. //! |FROM | TO |
  843. //! | |Legacy|Write|Read Write|Bi Read|Bi Write|Quad Read|Quad Write|
  844. //! +----------+------+-----+----------+-------+--------+---------+----------+
  845. //! |Legacy | yes | yes | yes | | | | |
  846. //! |Write | yes | yes | yes | yes | yes | yes | yes |
  847. //! |Read/Write| yes | yes | yes | yes | yes | yes | yes |
  848. //! |Bi Read | | yes | yes | yes | yes | | |
  849. //! |Bi write | | yes | yes | yes | yes | | |
  850. //! |Quad read | | yes | yes | | | yes | yes |
  851. //! |Quad write| | yes | yes | | | yes | yes |
  852. //! +----------+------+-----+----------+-------+--------+---------+----------+
  853. //! \endverbatim
  854. //!
  855. //! When using an advanced mode of operation, the SSI module must have been
  856. //! configured for eight data bits and the \b SSI_FRF_MOTO_MODE_0 protocol.
  857. //! The advanced mode operation that is selected applies only to data newly
  858. //! written into the FIFO; the data that is already present in the FIFO is
  859. //! handled using the advanced mode of operation in effect when that data was
  860. //! written.
  861. //!
  862. //! Switching into and out of legacy mode should only occur when the FIFO is
  863. //! empty.
  864. //!
  865. //! \return None.
  866. //
  867. //*****************************************************************************
  868. void
  869. SSIAdvModeSet(uint32_t ui32Base, uint32_t ui32Mode)
  870. {
  871. //
  872. // Check the arguments.
  873. //
  874. ASSERT(_SSIBaseValid(ui32Base));
  875. ASSERT((ui32Mode == SSI_ADV_MODE_LEGACY) ||
  876. (ui32Mode == SSI_ADV_MODE_WRITE) ||
  877. (ui32Mode == SSI_ADV_MODE_READ_WRITE) ||
  878. (ui32Mode == SSI_ADV_MODE_BI_READ) ||
  879. (ui32Mode == SSI_ADV_MODE_BI_WRITE) ||
  880. (ui32Mode == SSI_ADV_MODE_QUAD_READ) ||
  881. (ui32Mode == SSI_ADV_MODE_QUAD_WRITE));
  882. //
  883. // Set the SSI mode of operation.
  884. //
  885. HWREG(ui32Base + SSI_O_CR1) =
  886. ((HWREG(ui32Base + SSI_O_CR1) & ~(SSI_CR1_DIR | SSI_CR1_MODE_M)) |
  887. ui32Mode);
  888. }
  889. //*****************************************************************************
  890. //
  891. //! Puts a data element into the SSI transmit FIFO as the end of a frame.
  892. //!
  893. //! \param ui32Base specifies the SSI module base address.
  894. //! \param ui32Data is the data to be transmitted over the SSI interface.
  895. //!
  896. //! This function places the supplied data into the transmit FIFO of the
  897. //! specified SSI module, marking it as the end of a frame. If there is no
  898. //! space available in the transmit FIFO, this function waits until there is
  899. //! space available before returning. After this byte is transmitted by the
  900. //! SSI module, the FSS signal de-asserts for at least one SSI clock.
  901. //!
  902. //! \note The upper 24 bits of \e ui32Data are discarded by the hardware.
  903. //!
  904. //! \return None.
  905. //
  906. //*****************************************************************************
  907. void
  908. SSIAdvDataPutFrameEnd(uint32_t ui32Base, uint32_t ui32Data)
  909. {
  910. //
  911. // Check the arguments.
  912. //
  913. ASSERT(_SSIBaseValid(ui32Base));
  914. ASSERT((ui32Data & 0xffffff00) == 0);
  915. //
  916. // Wait until there is space.
  917. //
  918. while (!(HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF))
  919. {
  920. }
  921. //
  922. // Write the data to the SSI.
  923. //
  924. HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_EOM;
  925. HWREG(ui32Base + SSI_O_DR) = ui32Data;
  926. }
  927. //*****************************************************************************
  928. //
  929. //! Puts a data element into the SSI transmit FIFO as the end of a frame.
  930. //!
  931. //! \param ui32Base specifies the SSI module base address.
  932. //! \param ui32Data is the data to be transmitted over the SSI interface.
  933. //!
  934. //! This function places the supplied data into the transmit FIFO of the
  935. //! specified SSI module, marking it as the end of a frame. After this byte is
  936. //! transmitted by the SSI module, the FSS signal de-asserts for at least one
  937. //! SSI clock. If there is no space in the FIFO, then this function returns a
  938. //! zero.
  939. //!
  940. //! \note The upper 24 bits of \e ui32Data are discarded by the hardware.
  941. //!
  942. //! \return Returns the number of elements written to the SSI transmit FIFO.
  943. //
  944. //*****************************************************************************
  945. int32_t
  946. SSIAdvDataPutFrameEndNonBlocking(uint32_t ui32Base, uint32_t ui32Data)
  947. {
  948. //
  949. // Check the arguments.
  950. //
  951. ASSERT(_SSIBaseValid(ui32Base));
  952. ASSERT((ui32Data & 0xffffff00) == 0);
  953. //
  954. // Check for space to write.
  955. //
  956. if (HWREG(ui32Base + SSI_O_SR) & SSI_SR_TNF)
  957. {
  958. HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_EOM;
  959. HWREG(ui32Base + SSI_O_DR) = ui32Data;
  960. return (1);
  961. }
  962. else
  963. {
  964. return (0);
  965. }
  966. }
  967. //*****************************************************************************
  968. //
  969. //! Configures the SSI advanced mode to hold the SSIFss signal during the full
  970. //! transfer.
  971. //!
  972. //! \param ui32Base is the base address of the SSI module.
  973. //!
  974. //! This function configures the SSI module to de-assert the SSIFss signal
  975. //! during the entire data transfer when using one of the advanced modes
  976. //! (instead of briefly de-asserting it after every byte). When using this
  977. //! mode, SSIFss can be directly controlled via SSIAdvDataPutFrameEnd() and
  978. //! SSIAdvDataPutFrameEndNonBlocking().
  979. //!
  980. //! \return None.
  981. //
  982. //*****************************************************************************
  983. void
  984. SSIAdvFrameHoldEnable(uint32_t ui32Base)
  985. {
  986. //
  987. // Check the arguments.
  988. //
  989. ASSERT(_SSIBaseValid(ui32Base));
  990. //
  991. // Set the hold frame bit.
  992. //
  993. HWREG(ui32Base + SSI_O_CR1) |= SSI_CR1_FSSHLDFRM;
  994. }
  995. //*****************************************************************************
  996. //
  997. //! Configures the SSI advanced mode to de-assert the SSIFss signal after every
  998. //! byte transfer.
  999. //!
  1000. //! \param ui32Base is the base address of the SSI module.
  1001. //!
  1002. //! This function configures the SSI module to de-assert the SSIFss signal
  1003. //! for one SSI clock cycle after every byte is transferred using one of the
  1004. //! advanced modes (instead of leaving it asserted for the entire transfer).
  1005. //! This mode is the default operation.
  1006. //!
  1007. //! \return None.
  1008. //
  1009. //*****************************************************************************
  1010. void
  1011. SSIAdvFrameHoldDisable(uint32_t ui32Base)
  1012. {
  1013. //
  1014. // Check the arguments.
  1015. //
  1016. ASSERT(_SSIBaseValid(ui32Base));
  1017. //
  1018. // Clear the hold frame bit.
  1019. //
  1020. HWREG(ui32Base + SSI_O_CR1) &= ~(SSI_CR1_FSSHLDFRM);
  1021. }
  1022. //*****************************************************************************
  1023. //
  1024. // Close the Doxygen group.
  1025. //! @}
  1026. //
  1027. //*****************************************************************************