am_hal_ios.c 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337
  1. //*****************************************************************************
  2. //
  3. // am_hal_ios.c
  4. //! @file
  5. //!
  6. //! @brief Functions for interfacing with the IO Slave module
  7. //!
  8. //! @addtogroup ios2 IO Slave (SPI/I2C)
  9. //! @ingroup apollo2hal
  10. //! @{
  11. //
  12. //*****************************************************************************
  13. //*****************************************************************************
  14. //
  15. // Copyright (c) 2017, Ambiq Micro
  16. // All rights reserved.
  17. //
  18. // Redistribution and use in source and binary forms, with or without
  19. // modification, are permitted provided that the following conditions are met:
  20. //
  21. // 1. Redistributions of source code must retain the above copyright notice,
  22. // this list of conditions and the following disclaimer.
  23. //
  24. // 2. Redistributions in binary form must reproduce the above copyright
  25. // notice, this list of conditions and the following disclaimer in the
  26. // documentation and/or other materials provided with the distribution.
  27. //
  28. // 3. Neither the name of the copyright holder nor the names of its
  29. // contributors may be used to endorse or promote products derived from this
  30. // software without specific prior written permission.
  31. //
  32. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  33. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  36. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  37. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  38. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  39. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  40. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  42. // POSSIBILITY OF SUCH DAMAGE.
  43. //
  44. // This is part of revision 1.2.11 of the AmbiqSuite Development Package.
  45. //
  46. //*****************************************************************************
  47. #include <stdint.h>
  48. #include <stdbool.h>
  49. #include "am_mcu_apollo.h"
  50. //*****************************************************************************
  51. //
  52. // SRAM Buffer structure
  53. //
  54. //*****************************************************************************
  55. typedef struct
  56. {
  57. uint8_t *pui8Data;
  58. volatile uint32_t ui32WriteIndex;
  59. volatile uint32_t ui32ReadIndex;
  60. volatile uint32_t ui32Length;
  61. uint32_t ui32FifoInc;
  62. uint32_t ui32Capacity;
  63. }
  64. am_hal_ios_buffer_t;
  65. am_hal_ios_buffer_t g_sSRAMBuffer;
  66. //*****************************************************************************
  67. //
  68. // Forward declarations of static funcitons.
  69. //
  70. //*****************************************************************************
  71. static void am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer,
  72. void *pvArray, uint32_t ui32Bytes);
  73. static void fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes);
  74. //*****************************************************************************
  75. //
  76. // Function-like macros.
  77. //
  78. //*****************************************************************************
  79. #define am_hal_ios_buffer_empty(psBuffer) \
  80. ((psBuffer)->ui32Length == 0)
  81. #define am_hal_ios_buffer_full(psBuffer) \
  82. ((psBuffer)->ui32Length == (psBuffer)->ui32Capacity)
  83. #define am_hal_ios_buffer_data_left(psBuffer) \
  84. ((psBuffer)->ui32Length)
  85. //*****************************************************************************
  86. //
  87. // Global Variables
  88. //
  89. //*****************************************************************************
  90. volatile uint8_t * const am_hal_ios_pui8LRAM = (uint8_t *)REG_IOSLAVE_BASEADDR;
  91. uint8_t *g_pui8FIFOBase = (uint8_t *) REG_IOSLAVE_BASEADDR;
  92. uint8_t *g_pui8FIFOEnd = (uint8_t *) REG_IOSLAVE_BASEADDR;
  93. uint8_t *g_pui8FIFOPtr = (uint8_t *) REG_IOSLAVE_BASEADDR;
  94. uint8_t g_ui32HwFifoSize = 0;
  95. uint32_t g_ui32FifoBaseOffset = 0;
  96. //*****************************************************************************
  97. //
  98. // Checks to see if this processor is a Rev B2 device.
  99. //
  100. // This is needed to disable SHELBY-1654 workaround.
  101. //
  102. //*****************************************************************************
  103. bool
  104. isRevB2(void)
  105. {
  106. //
  107. // Check to make sure the major rev is B and the minor rev is 2.
  108. //
  109. return ( (AM_REG(MCUCTRL, CHIPREV) & 0xFF) == \
  110. (AM_REG_MCUCTRL_CHIPREV_REVMAJ_B | (AM_REG_MCUCTRL_CHIPREV_REVMIN_REV0 + 2)) );
  111. }
  112. //*****************************************************************************
  113. //
  114. //! @brief Enable the IOS in the power control block.
  115. //!
  116. //! This function enables the IOS module in the power control block.
  117. //!
  118. //! @return None.
  119. //
  120. //*****************************************************************************
  121. void
  122. am_hal_ios_pwrctrl_enable(void)
  123. {
  124. am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
  125. }
  126. //*****************************************************************************
  127. //
  128. //! @brief Disable the IOS in the power control block.
  129. //!
  130. //! This function disables the IOS module in the power control block.
  131. //!
  132. //! @return None.
  133. //
  134. //*****************************************************************************
  135. void
  136. am_hal_ios_pwrctrl_disable(void)
  137. {
  138. am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_IOS);
  139. }
  140. //*****************************************************************************
  141. //
  142. //! @brief Enables the IOS module
  143. //!
  144. //! This function enables the IOSLAVE module using the IFCEN bitfield in the
  145. //! IOSLAVE_CFG register.
  146. //!
  147. //! @return None.
  148. //
  149. //*****************************************************************************
  150. void
  151. am_hal_ios_enable(uint32_t ui32Module)
  152. {
  153. AM_REGn(IOSLAVE, ui32Module, CFG) |= AM_REG_IOSLAVE_CFG_IFCEN(1);
  154. }
  155. //*****************************************************************************
  156. //
  157. //! @brief Disables the IOSLAVE module.
  158. //!
  159. //! This function disables the IOSLAVE module using the IFCEN bitfield in the
  160. //! IOSLAVE_CFG register.
  161. //!
  162. //! @return None.
  163. //
  164. //*****************************************************************************
  165. void
  166. am_hal_ios_disable(uint32_t ui32Module)
  167. {
  168. AM_REGn(IOSLAVE, ui32Module, CFG) &= ~(AM_REG_IOSLAVE_CFG_IFCEN(1));
  169. }
  170. //*****************************************************************************
  171. //
  172. //! @brief Configure the IOS module.
  173. //!
  174. //! This function reads the an \e am_hal_ios_config_t structure and uses it to
  175. //! set up the IO Slave module. Please see the information on the configuration
  176. //! structure for more information on the parameters that may be set by this
  177. //! function.
  178. //!
  179. //! @return None.
  180. //
  181. //*****************************************************************************
  182. void
  183. am_hal_ios_config(am_hal_ios_config_t *psConfig)
  184. {
  185. uint32_t ui32LRAMConfig;
  186. am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_IOS);
  187. //
  188. // Record the FIFO parameters for later use.
  189. //
  190. g_pui8FIFOBase = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32FIFOBase);
  191. g_pui8FIFOEnd = (uint8_t *)(REG_IOSLAVE_BASEADDR + psConfig->ui32RAMBase);
  192. g_ui32HwFifoSize = g_pui8FIFOEnd - g_pui8FIFOBase;
  193. g_ui32FifoBaseOffset = psConfig->ui32FIFOBase;
  194. //
  195. // Caluclate the value for the IO Slave FIFO configuration register.
  196. //
  197. ui32LRAMConfig = AM_REG_IOSLAVE_FIFOCFG_ROBASE(psConfig->ui32ROBase >> 3);
  198. ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOBASE(psConfig->ui32FIFOBase >> 3);
  199. ui32LRAMConfig |= AM_REG_IOSLAVE_FIFOCFG_FIFOMAX(psConfig->ui32RAMBase >> 3);
  200. //
  201. // Just in case, disable the IOS
  202. //
  203. am_hal_ios_disable(0);
  204. //
  205. // Write the configuration register with the user's selected interface
  206. // characteristics.
  207. //
  208. AM_REG(IOSLAVE, CFG) = psConfig->ui32InterfaceSelect;
  209. //
  210. // Write the FIFO configuration register to set the memory map for the LRAM.
  211. //
  212. AM_REG(IOSLAVE, FIFOCFG) = ui32LRAMConfig;
  213. //
  214. // Enable the IOS. The following configuration options can't be set while
  215. // the IOS is disabled.
  216. //
  217. am_hal_ios_enable(0);
  218. //
  219. // Initialize the FIFO pointer to the beginning of the FIFO section.
  220. //
  221. am_hal_ios_fifo_ptr_set(psConfig->ui32FIFOBase);
  222. //
  223. // Write the FIFO threshold register.
  224. //
  225. AM_REG(IOSLAVE, FIFOTHR) = psConfig->ui32FIFOThreshold;
  226. }
  227. //*****************************************************************************
  228. //
  229. //! @brief Set bits in the HOST side IOINTCTL register.
  230. //!
  231. //! This function may be used to set an interrupt bit to the host.
  232. //!
  233. //! @return None.
  234. //
  235. //*****************************************************************************
  236. void
  237. am_hal_ios_host_int_set(uint32_t ui32Interrupt)
  238. {
  239. //
  240. // Set a bit that will cause an interrupt to the host.
  241. //
  242. AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTSET(ui32Interrupt);
  243. }
  244. //*****************************************************************************
  245. //
  246. //! @brief Clear bits in the HOST side IOINTCTL register.
  247. //!
  248. //! This function may be used to clear an interrupt bit to the host.
  249. //!
  250. //! @return None.
  251. //
  252. //*****************************************************************************
  253. void
  254. am_hal_ios_host_int_clear(uint32_t ui32Interrupt)
  255. {
  256. //
  257. // Clear bits that will cause an interrupt to the host.
  258. //
  259. AM_REG(IOSLAVE, IOINTCTL) = AM_REG_IOSLAVE_IOINTCTL_IOINTCLR(ui32Interrupt);
  260. }
  261. //*****************************************************************************
  262. //
  263. //! @brief Get the bits in the HOST side IOINTCTL register.
  264. //!
  265. //! This function may be used to read the host side interrupt bits.
  266. //!
  267. //! @return None.
  268. //
  269. //*****************************************************************************
  270. uint32_t
  271. am_hal_ios_host_int_get(void)
  272. {
  273. //
  274. // return the value of the bits that will cause an interrupt to the host.
  275. //
  276. return AM_BFR(IOSLAVE, IOINTCTL, IOINT);
  277. }
  278. //*****************************************************************************
  279. //
  280. //! @brief Get the enable bits in the HOST side IOINTCTL register.
  281. //!
  282. //! This function may be used to read the host side interrupt bits.
  283. //!
  284. //! @return None.
  285. //
  286. //*****************************************************************************
  287. uint32_t
  288. am_hal_ios_host_int_enable_get(void)
  289. {
  290. //
  291. // return the value of the bits that will cause an interrupt to the host.
  292. //
  293. return AM_BFR(IOSLAVE, IOINTCTL, IOINTEN);
  294. }
  295. //*****************************************************************************
  296. //
  297. //! @brief Enable an IOS Access Interrupt.
  298. //!
  299. //! This function may be used to enable an interrupt to the NVIC.
  300. //!
  301. //! @return None.
  302. //
  303. //*****************************************************************************
  304. void
  305. am_hal_ios_access_int_enable(uint32_t ui32Interrupt)
  306. {
  307. //
  308. // OR the desired interrupt into the enable register.
  309. //
  310. AM_REG(IOSLAVE, REGACCINTEN) |= ui32Interrupt;
  311. }
  312. //*****************************************************************************
  313. //
  314. //! @brief Return all enabled IOS Access Interrupts.
  315. //!
  316. //! This function may be used to return all enabled IOS Access interrupts.
  317. //!
  318. //! @return the enabled interrrupts.
  319. //
  320. //*****************************************************************************
  321. uint32_t
  322. am_hal_ios_access_int_enable_get(void)
  323. {
  324. //
  325. // Return the enabled interrupts.
  326. //
  327. return AM_REG(IOSLAVE, REGACCINTEN);
  328. }
  329. //*****************************************************************************
  330. //
  331. //! @brief Disable an IOS Access Interrupt.
  332. //!
  333. //! This function may be used to disable an interrupt to the NVIC.
  334. //!
  335. //! @return None.
  336. //
  337. //*****************************************************************************
  338. void
  339. am_hal_ios_access_int_disable(uint32_t ui32Interrupt)
  340. {
  341. //
  342. // Clear the desired bit from the interrupt enable register.
  343. //
  344. AM_REG(IOSLAVE, REGACCINTEN) &= ~(ui32Interrupt);
  345. }
  346. //*****************************************************************************
  347. //
  348. //! @brief Clear an IOS Access Interrupt.
  349. //!
  350. //! This function may be used to clear an interrupt to the NVIC.
  351. //!
  352. //! @return None.
  353. //
  354. //*****************************************************************************
  355. void
  356. am_hal_ios_access_int_clear(uint32_t ui32Interrupt)
  357. {
  358. //
  359. // Use the interrupt clear register to deactivate the chosen interrupt.
  360. //
  361. AM_REG(IOSLAVE, REGACCINTCLR) = ui32Interrupt;
  362. }
  363. //*****************************************************************************
  364. //
  365. //! @brief Set an IOS Access Interrupt.
  366. //!
  367. //! This function may be used to set an interrupt to the NVIC.
  368. //!
  369. //! @return None.
  370. //
  371. //*****************************************************************************
  372. void
  373. am_hal_ios_access_int_set(uint32_t ui32Interrupt)
  374. {
  375. //
  376. // Use the interrupt set register to activate the chosen interrupt.
  377. //
  378. AM_REG(IOSLAVE, REGACCINTSET) = ui32Interrupt;
  379. }
  380. //*****************************************************************************
  381. //
  382. //! @brief Check the status of an IOS Access Interrupt.
  383. //!
  384. //! @param bEnabledOnly - return only the enabled interrupt status.
  385. //!
  386. //! This function may be used to return the enabled interrupt status.
  387. //!
  388. //! @return the enabled interrupt status.
  389. //
  390. //*****************************************************************************
  391. uint32_t
  392. am_hal_ios_access_int_status_get(bool bEnabledOnly)
  393. {
  394. if ( bEnabledOnly )
  395. {
  396. uint32_t u32RetVal = AM_REG(IOSLAVE, REGACCINTSTAT);
  397. return u32RetVal & AM_REG(IOSLAVE, REGACCINTEN);
  398. }
  399. else
  400. {
  401. return AM_REG(IOSLAVE, REGACCINTSTAT);
  402. }
  403. }
  404. //*****************************************************************************
  405. //
  406. //! @brief Enable an IOS Interrupt.
  407. //!
  408. //! @param ui32Interrupt - desired interrupts.
  409. //!
  410. //! This function may be used to enable an interrupt to the NVIC.
  411. //!
  412. //! @return None.
  413. //
  414. //*****************************************************************************
  415. void
  416. am_hal_ios_int_enable(uint32_t ui32Interrupt)
  417. {
  418. //
  419. // OR the desired interrupt into the enable register.
  420. //
  421. AM_REG(IOSLAVE, INTEN) |= ui32Interrupt;
  422. }
  423. //*****************************************************************************
  424. //
  425. //! @brief Return all enabled IOS Interrupts.
  426. //!
  427. //! This function may be used to return all enabled IOS interrupts.
  428. //!
  429. //! @return the enabled interrrupts.
  430. //
  431. //*****************************************************************************
  432. uint32_t
  433. am_hal_ios_int_enable_get(void)
  434. {
  435. //
  436. // Return the enabled interrupts.
  437. //
  438. return AM_REG(IOSLAVE, INTEN);
  439. }
  440. //*****************************************************************************
  441. //
  442. //! @brief Disable an IOS Interrupt.
  443. //!
  444. //! @param ui32Interrupt - desired interrupts.
  445. //!
  446. //! This function may be used to disable an interrupt to the NVIC.
  447. //!
  448. //! @return None.
  449. //
  450. //*****************************************************************************
  451. void
  452. am_hal_ios_int_disable(uint32_t ui32Interrupt)
  453. {
  454. //
  455. // Clear the desired bit from the interrupt enable register.
  456. //
  457. AM_REG(IOSLAVE, INTEN) &= ~(ui32Interrupt);
  458. }
  459. //*****************************************************************************
  460. //
  461. //! @brief Clear an IOS Interrupt.
  462. //!
  463. //! @param ui32Interrupt - desired interrupts.
  464. //!
  465. //! This function may be used to clear an interrupt to the NVIC.
  466. //!
  467. //! @return None.
  468. //
  469. //*****************************************************************************
  470. void
  471. am_hal_ios_int_clear(uint32_t ui32Interrupt)
  472. {
  473. //
  474. // Use the interrupt clear register to deactivate the chosen interrupt.
  475. //
  476. AM_REG(IOSLAVE, INTCLR) = ui32Interrupt;
  477. }
  478. //*****************************************************************************
  479. //
  480. //! @brief Set an IOS Interrupt.
  481. //!
  482. //! @param ui32Interrupt - desired interrupts.
  483. //!
  484. //! This function may be used to set an interrupt to the NVIC.
  485. //!
  486. //! @return None.
  487. //
  488. //*****************************************************************************
  489. void
  490. am_hal_ios_int_set(uint32_t ui32Interrupt)
  491. {
  492. //
  493. // Use the interrupt clear register to deactivate the chosen interrupt.
  494. //
  495. AM_REG(IOSLAVE, INTSET) = ui32Interrupt;
  496. }
  497. //*****************************************************************************
  498. //
  499. //! @brief Write to the LRAM.
  500. //!
  501. //! @param ui32Offset - offset into the LRAM to write.
  502. //! @param ui8Value - value to be written.
  503. //!
  504. //! This function writes ui8Value to offset ui32Offset inside the LRAM.
  505. //!
  506. //! @return None.
  507. //
  508. //*****************************************************************************
  509. void
  510. am_hal_ios_lram_write(uint32_t ui32Offset, uint8_t ui8Value)
  511. {
  512. //
  513. // Write the LRAM.
  514. //
  515. am_hal_ios_pui8LRAM[ui32Offset] = ui8Value;
  516. }
  517. //*****************************************************************************
  518. //
  519. //! @brief Read from the LRAM.
  520. //!
  521. //! @param ui32Offset - offset into the LRAM to read.
  522. //!
  523. //! This function read from offset ui32Offset inside the LRAM.
  524. //!
  525. //! @return the value at ui32Offset.
  526. //
  527. //*****************************************************************************
  528. uint8_t
  529. am_hal_ios_lram_read(uint32_t ui32Offset)
  530. {
  531. //
  532. // Read the LRAM.
  533. //
  534. return am_hal_ios_pui8LRAM[ui32Offset];
  535. }
  536. //*****************************************************************************
  537. //
  538. //! @brief Check the status of an IOS Interrupt.
  539. //!
  540. //! @param bEnabledOnly - return only the enabled interrupt status.
  541. //!
  542. //! This function may be used to return the enabled interrupt status.
  543. //!
  544. //! @return the enabled interrupt status.
  545. //
  546. //*****************************************************************************
  547. uint32_t
  548. am_hal_ios_int_status_get(bool bEnabledOnly)
  549. {
  550. if ( bEnabledOnly )
  551. {
  552. uint32_t u32RetVal = AM_REG(IOSLAVE, INTSTAT);
  553. return u32RetVal & AM_REG(IOSLAVE, INTEN);
  554. }
  555. else
  556. {
  557. return AM_REG(IOSLAVE, INTSTAT);
  558. }
  559. }
  560. //*****************************************************************************
  561. //
  562. //! @brief Check the amount of space used in the FIFO
  563. //!
  564. //! This function returns the available data in the overall FIFO yet to be
  565. //! read by the host. This takes into account the SRAM buffer and hardware FIFO
  566. //!
  567. //! @return Bytes used in the Overall FIFO.
  568. //
  569. //*****************************************************************************
  570. uint32_t
  571. am_hal_ios_fifo_space_used(void)
  572. {
  573. uint32_t ui32Val;
  574. uint32_t ui32Primask;
  575. //
  576. // Start a critical section for thread safety.
  577. //
  578. ui32Primask = am_hal_interrupt_master_disable();
  579. ui32Val = g_sSRAMBuffer.ui32Length;
  580. ui32Val += AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
  581. //
  582. // End the critical section
  583. //
  584. am_hal_interrupt_master_set(ui32Primask);
  585. return ui32Val;
  586. }
  587. //*****************************************************************************
  588. //
  589. //! @brief Check the amount of space left in the FIFO
  590. //!
  591. //! This function returns the available space in the overall FIFO to accept
  592. //! new data. This takes into account the SRAM buffer and hardware FIFO
  593. //!
  594. //! @return Bytes left in the Overall FIFO.
  595. //
  596. //*****************************************************************************
  597. uint32_t
  598. am_hal_ios_fifo_space_left(void)
  599. {
  600. uint32_t ui32Val;
  601. uint32_t ui32Primask;
  602. //
  603. // Start a critical section for thread safety.
  604. //
  605. ui32Primask = am_hal_interrupt_master_disable();
  606. //
  607. // We waste one byte in HW FIFO
  608. //
  609. ui32Val = g_sSRAMBuffer.ui32Capacity + g_ui32HwFifoSize - 1;
  610. ui32Val -= g_sSRAMBuffer.ui32Length;
  611. ui32Val -= AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
  612. //
  613. // End the critical section
  614. //
  615. am_hal_interrupt_master_set(ui32Primask);
  616. return ui32Val;
  617. }
  618. //*****************************************************************************
  619. //
  620. //! @brief Check the amount of space left in the hardware FIFO
  621. //!
  622. //! This function reads the IOSLAVE FIFOPTR register and determines the amount
  623. //! of space left in the IOS LRAM FIFO.
  624. //!
  625. //! @return Bytes left in the IOS FIFO.
  626. //
  627. //*****************************************************************************
  628. static uint32_t
  629. fifo_space_left(void)
  630. {
  631. //
  632. // We waste one byte in HW FIFO
  633. //
  634. return ((uint32_t)g_ui32HwFifoSize- AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ) - 1);
  635. }
  636. //*****************************************************************************
  637. //
  638. // Helper function for managing IOS FIFO writes.
  639. //
  640. //*****************************************************************************
  641. static void
  642. fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
  643. {
  644. uint8_t *pFifoPtr = g_pui8FIFOPtr;
  645. uint8_t *pFifoBase = g_pui8FIFOBase;
  646. uint8_t *pFifoEnd = g_pui8FIFOEnd;
  647. while ( ui32NumBytes )
  648. {
  649. //
  650. // Write the data to the FIFO
  651. //
  652. *pFifoPtr++ = *pui8Data++;
  653. ui32NumBytes--;
  654. //
  655. // Make sure to wrap the FIFO pointer if necessary.
  656. //
  657. if ( pFifoPtr == pFifoEnd )
  658. {
  659. pFifoPtr = pFifoBase;
  660. }
  661. }
  662. g_pui8FIFOPtr = pFifoPtr;
  663. }
  664. //
  665. // Assembly code below assumes 8bit FIFOSIZ field aligned at a byte boundary
  666. //
  667. #if (((AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S) != 0xFF) \
  668. || (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S & 0x3))
  669. #error "FIFOSIZ not 8bit value aligned at byte offset"
  670. #endif
  671. //
  672. // Byte offset of FIFOSIZ field in FIFOPTR register
  673. //
  674. #define BYTEOFFSET_FIFOSIZE (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S >> 3)
  675. //*****************************************************************************
  676. //
  677. // Helper function in assembly for implementing the ReSync
  678. //
  679. //*****************************************************************************
  680. #if defined(__GNUC_STDC_INLINE__)
  681. #if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
  682. #error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
  683. #endif
  684. __attribute__((naked))
  685. static void
  686. internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
  687. {
  688. __asm
  689. (
  690. " push {r3,r4}\n\t" // Save r3, r4 - used by this function
  691. "__internal_resync_fifoSize_loop:\n\t"
  692. " ldr r4, [r2]\n\t" // Load FIFOPTR register in r4
  693. " ubfx r3, r4, #8, #8\n\t" // Extract hwFifoSize to r3
  694. " uxtb r4, r4\n\t" // Extract rdOffset in r4
  695. " subs r4, r0, r4\n\t" // fifoSize in r4 = wrOffset - rdOffset
  696. " it cc\n\t" // if (wrOffset < rdOffset)
  697. " addcc r4, r4, r1\n\t" // fifoSize = maxFifoSize - (rdOffset - wrOffset)
  698. " cmp r3, r4\n\t" // (hwFifoSize != fifoSize)
  699. " beq __internal_resync_fifosize_done\n\t"
  700. " strb r4, [r2, #1]\n\t" // Overwrite FIFOSIZ value with fifoSize
  701. " b __internal_resync_fifoSize_loop\n\t" // Repeat the check
  702. "__internal_resync_fifosize_done:\n\t"
  703. " pop {r3,r4}\n\t" // Restore registers
  704. " bx lr\n\t"
  705. );
  706. }
  707. #elif defined(__ARMCC_VERSION)
  708. __asm static void
  709. internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
  710. {
  711. push {r3, r4} // Save r3, r4 - used by this function
  712. internal_resync_fifoSize_loop
  713. ldr r4, [r2] // Load FIFOPTR register in r4
  714. ubfx r3, r4, #AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S, #8 // Extract hwFifoSize to r3
  715. uxtb r4, r4 // Extract rdOffset in r4
  716. subs r4, r0, r4 // fifoSize in r4 = wrOffset - rdOffset
  717. it cc // if (wrOffset < rdOffset),
  718. addcc r4, r4, r1 // fifoSize = maxFifoSize - (rdOffset - wrOffset)
  719. cmp r3, r4 // (hwFifoSize != fifoSize)
  720. beq internal_resync_fifosize_done
  721. strb r4, [r2, #1] // Overwrite FIFOSIZ value with fifoSize
  722. b internal_resync_fifoSize_loop // Repeat the check
  723. internal_resync_fifosize_done
  724. pop {r3, r4} // Restore registers
  725. bx lr
  726. }
  727. #elif defined(__IAR_SYSTEMS_ICC__)
  728. #if (AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S != 8)
  729. #error "AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S not 8"
  730. #endif
  731. __stackless static void
  732. internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
  733. {
  734. __asm volatile (
  735. " push {r3,r4}\n" // Save r3, r4 - used by this function
  736. "__internal_resync_fifoSize_loop:\n"
  737. " ldr r4, [r2]\n" // Load FIFOPTR register in r4
  738. " ubfx r3, r4, #8, #8\n" // Extract hwFifoSize to r3
  739. " uxtb r4, r4\n" // Extract rdOffset in r4
  740. " subs r4, r0, r4\n" // fifoSize in r4 = wrOffset - rdOffset
  741. " it cc\n"
  742. " addcc r4, r4, r1\n" // fifoSize = maxFifoSize - (rdOffset - wrOffset)
  743. " cmp r3, r4\n" // (fifoSize != hwFifoSize)
  744. " beq __internal_resync_fifosize_done\n"
  745. " strb r4, [r2, #1]\n" // Overwrite FIFOSIZ value with fifoSize
  746. " b __internal_resync_fifoSize_loop\n" // Repeat the check
  747. "__internal_resync_fifosize_done:\n"
  748. " pop {r3,r4}\n" // Restore registers
  749. " bx lr\n"
  750. );
  751. }
  752. #else
  753. static void
  754. internal_resync_fifoSize(uint32_t wrOffset, uint32_t maxFifoSize, uint32_t hwFifoPtrRegAddr)
  755. {
  756. uint32_t fifoSize;
  757. uint32_t hwFifoPtrReg;
  758. uint32_t rdOffset;
  759. uint32_t hwFifoSize;
  760. hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
  761. rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
  762. hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
  763. // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
  764. fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (maxFifoSize - (rdOffset - wrOffset)));
  765. while ( fifoSize != hwFifoSize )
  766. {
  767. // Overwite correct FIFOSIZ
  768. // Need to do a Byte Write to make sure the FIFOPTR is not overwritten
  769. *((uint8_t *)(hwFifoPtrRegAddr + BYTEOFFSET_FIFOSIZE)) = fifoSize;
  770. // Read back the register and check for consistency
  771. hwFifoPtrReg = AM_REGVAL(hwFifoPtrRegAddr);
  772. rdOffset = ((hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOPTR_S);
  773. hwFifoSize = (hwFifoPtrReg & AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_M) >> AM_REG_IOSLAVE_FIFOPTR_FIFOSIZ_S;
  774. // By wasting one byte in hardware FIFO, we're guaranteed that fifoSize does not need special handling for FULL FIFO case
  775. fifoSize = ((wrOffset >= rdOffset) ? (wrOffset - rdOffset) : (hwFifoSize - (rdOffset - wrOffset)));
  776. }
  777. }
  778. #endif
  779. //
  780. // Address of the FIFOPTR register
  781. //
  782. #define AM_REG_IOS_FIFOPTR (REG_IOSLAVE_BASEADDR + AM_REG_IOSLAVE_FIFOPTR_O)
  783. // When the FIFO is being replenished by the SW, at the same time as host is
  784. // reading from it, there is a possible race condition, where the hardware decrement
  785. // of FIFOSIZ as a result of read gets overwritten by hardware increment due to
  786. // write.
  787. // This function re-sync's the FIFOSIZ to ensure such errors do not accumulate
  788. void
  789. resync_fifoSize(void)
  790. {
  791. uint32_t ui32Primask;
  792. uint32_t wrOffset = (uint32_t)g_pui8FIFOPtr - (uint32_t)am_hal_ios_pui8LRAM;
  793. //
  794. // Start a critical section for thread safety.
  795. //
  796. ui32Primask = am_hal_interrupt_master_disable();
  797. internal_resync_fifoSize(wrOffset, g_ui32HwFifoSize, AM_REG_IOS_FIFOPTR);
  798. // Clear interrupts for IOS which could be spuriously triggered
  799. AM_REG(IOSLAVE, REGACCINTCLR) = (AM_HAL_IOS_INT_FSIZE | AM_HAL_IOS_INT_FOVFL | AM_HAL_IOS_INT_FUNDFL);
  800. //
  801. // End the critical section
  802. //
  803. am_hal_interrupt_master_set(ui32Primask);
  804. return;
  805. }
  806. //*****************************************************************************
  807. //
  808. //! @brief Transfer any available data from the IOS SRAM buffer to the FIFO.
  809. //!
  810. //! This function is meant to be called from an interrupt handler for the
  811. //! ioslave module. It checks the IOS FIFO interrupt status for a threshold
  812. //! event, and transfers data from an SRAM buffer into the IOS FIFO.
  813. //!
  814. //! @param ui32Status should be set to the ios interrupt status at the time of
  815. //! ISR entry.
  816. //!
  817. //! @return None.
  818. //
  819. //*****************************************************************************
  820. void
  821. am_hal_ios_fifo_service(uint32_t ui32Status)
  822. {
  823. uint32_t thresh;
  824. uint32_t freeSpace, usedSpace, chunk1, chunk2, ui32WriteIndex;
  825. //
  826. // Check for FIFO size interrupts.
  827. //
  828. if ( ui32Status & AM_HAL_IOS_INT_FSIZE )
  829. {
  830. thresh = AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR);
  831. //
  832. // While the FIFO is at or below threshold Add more data
  833. // If Fifo level is above threshold, we're guaranteed an FSIZ interrupt
  834. //
  835. while ( g_sSRAMBuffer.ui32Length &&
  836. ((usedSpace = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ)) <= thresh) )
  837. {
  838. //
  839. // So, we do have some data in SRAM which needs to be moved to FIFO.
  840. // A chunk of data is a continguous set of bytes in SRAM that can be
  841. // written to FIFO. Determine the chunks of data from SRAM that can
  842. // be written. Up to two chunks possible
  843. //
  844. ui32WriteIndex = g_sSRAMBuffer.ui32WriteIndex;
  845. chunk1 = ((ui32WriteIndex > (uint32_t)g_sSRAMBuffer.ui32ReadIndex) ? \
  846. (ui32WriteIndex - (uint32_t)g_sSRAMBuffer.ui32ReadIndex) : \
  847. (g_sSRAMBuffer.ui32Capacity - (uint32_t)g_sSRAMBuffer.ui32ReadIndex));
  848. chunk2 = g_sSRAMBuffer.ui32Length - chunk1;
  849. // We waste one byte in HW FIFO
  850. freeSpace = g_ui32HwFifoSize - usedSpace - 1;
  851. // Write data in chunks
  852. // Determine the chunks of data from SRAM that can be written
  853. if ( chunk1 > freeSpace )
  854. {
  855. fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
  856. //
  857. // Advance the read index, wrapping if needed.
  858. //
  859. g_sSRAMBuffer.ui32ReadIndex += freeSpace;
  860. // No need to check for wrap as we wrote less than chunk1
  861. //
  862. // Adjust the length value to reflect the change.
  863. //
  864. g_sSRAMBuffer.ui32Length -= freeSpace;
  865. }
  866. else
  867. {
  868. fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk1);
  869. //
  870. // Update the read index - wrapping as needed
  871. //
  872. g_sSRAMBuffer.ui32ReadIndex += chunk1;
  873. g_sSRAMBuffer.ui32ReadIndex %= g_sSRAMBuffer.ui32Capacity;
  874. //
  875. // Adjust the length value to reflect the change.
  876. //
  877. g_sSRAMBuffer.ui32Length -= chunk1;
  878. freeSpace -= chunk1;
  879. if ( freeSpace && chunk2 )
  880. {
  881. if ( chunk2 > freeSpace )
  882. {
  883. fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), freeSpace);
  884. //
  885. // Advance the read index, wrapping if needed.
  886. //
  887. g_sSRAMBuffer.ui32ReadIndex += freeSpace;
  888. // No need to check for wrap in chunk2
  889. //
  890. // Adjust the length value to reflect the change.
  891. //
  892. g_sSRAMBuffer.ui32Length -= freeSpace;
  893. }
  894. else
  895. {
  896. fifo_write((uint8_t *)(g_sSRAMBuffer.pui8Data + g_sSRAMBuffer.ui32ReadIndex), chunk2);
  897. //
  898. // Advance the read index, wrapping if needed.
  899. //
  900. g_sSRAMBuffer.ui32ReadIndex += chunk2;
  901. // No need to check for wrap in chunk2
  902. //
  903. // Adjust the length value to reflect the change.
  904. //
  905. g_sSRAMBuffer.ui32Length -= chunk2;
  906. }
  907. }
  908. }
  909. if (!isRevB2())
  910. {
  911. resync_fifoSize();
  912. }
  913. //
  914. // Need to retake the FIFO space, after Threshold interrupt has been reenabled
  915. // Clear any spurious FSIZE interrupt that might have got raised
  916. //
  917. AM_BFW(IOSLAVE, INTCLR, FSIZE, 1);
  918. }
  919. }
  920. }
  921. //*****************************************************************************
  922. //
  923. //! @brief Writes the specified number of bytes to the IOS fifo.
  924. //!
  925. //! @param pui8Data is a pointer to the data to be written to the fifo.
  926. //! @param ui32NumBytes is the number of bytes to send.
  927. //!
  928. //! This function will write data from the caller-provided array to the IOS
  929. //! LRAM FIFO. If there is no space in the LRAM FIFO, the data will be copied
  930. //! to a temporary SRAM buffer instead.
  931. //!
  932. //! The maximum message size for the IO Slave is 1023 bytes.
  933. //!
  934. //! @note In order for SRAM copy operations in the function to work correctly,
  935. //! the \e am_hal_ios_buffer_service() function must be called in the ISR for
  936. //! the ioslave module.
  937. //!
  938. //! @return Number of bytes written (could be less than ui32NumBytes, if not enough space)
  939. //
  940. //*****************************************************************************
  941. uint32_t
  942. am_hal_ios_fifo_write(uint8_t *pui8Data, uint32_t ui32NumBytes)
  943. {
  944. uint32_t ui32FIFOSpace;
  945. uint32_t ui32SRAMSpace;
  946. uint32_t ui32SRAMLength;
  947. uint32_t ui32Primask;
  948. uint32_t totalBytes = ui32NumBytes;
  949. //
  950. // This operation will only work properly if an SRAM buffer has been
  951. // allocated. Make sure that am_hal_ios_fifo_buffer_init() has been called,
  952. // and the buffer pointer looks valid.
  953. //
  954. am_hal_debug_assert(g_sSRAMBuffer.pui8Data != 0);
  955. if ( ui32NumBytes == 0 )
  956. {
  957. return 0;
  958. }
  959. //
  960. // Start a critical section for thread safety.
  961. //
  962. ui32Primask = am_hal_interrupt_master_disable();
  963. ui32SRAMLength = g_sSRAMBuffer.ui32Length;
  964. //
  965. // End the critical section
  966. //
  967. am_hal_interrupt_master_set(ui32Primask);
  968. //
  969. // If the SRAM buffer is empty, we should just write directly to the FIFO.
  970. //
  971. if ( ui32SRAMLength == 0 )
  972. {
  973. ui32FIFOSpace = fifo_space_left();
  974. //
  975. // If the whole message fits, send it now.
  976. //
  977. if ( ui32NumBytes <= ui32FIFOSpace )
  978. {
  979. fifo_write(pui8Data, ui32NumBytes);
  980. ui32NumBytes = 0;
  981. }
  982. else
  983. {
  984. fifo_write(pui8Data, ui32FIFOSpace);
  985. ui32NumBytes -= ui32FIFOSpace;
  986. pui8Data += ui32FIFOSpace;
  987. };
  988. if (!isRevB2())
  989. {
  990. resync_fifoSize();
  991. }
  992. }
  993. //
  994. // If there's still data, write it to the SRAM buffer.
  995. //
  996. if ( ui32NumBytes )
  997. {
  998. uint32_t idx, writeIdx, capacity, fifoSize;
  999. ui32SRAMSpace = g_sSRAMBuffer.ui32Capacity - ui32SRAMLength;
  1000. writeIdx = g_sSRAMBuffer.ui32WriteIndex;
  1001. capacity = g_sSRAMBuffer.ui32Capacity;
  1002. //
  1003. // Make sure that the data will fit inside the SRAM buffer.
  1004. //
  1005. if ( ui32SRAMSpace > ui32NumBytes )
  1006. {
  1007. ui32SRAMSpace = ui32NumBytes;
  1008. }
  1009. //
  1010. // If the data will fit, write it to the SRAM buffer.
  1011. //
  1012. for ( idx = 0; idx < ui32SRAMSpace; idx++ )
  1013. {
  1014. g_sSRAMBuffer.pui8Data[(idx + writeIdx) % capacity] = pui8Data[idx];
  1015. }
  1016. ui32NumBytes -= idx;
  1017. //
  1018. // Start a critical section for thread safety before updating length & wrIdx.
  1019. //
  1020. ui32Primask = am_hal_interrupt_master_disable();
  1021. //
  1022. // Advance the write index, making sure to wrap if necessary.
  1023. //
  1024. g_sSRAMBuffer.ui32WriteIndex = (idx + writeIdx) % capacity;
  1025. //
  1026. // Update the length value appropriately.
  1027. //
  1028. g_sSRAMBuffer.ui32Length += idx;
  1029. //
  1030. // End the critical section
  1031. //
  1032. am_hal_interrupt_master_set(ui32Primask);
  1033. // It is possible that there is a race condition that the FIFO level has
  1034. // gone below the threshold by the time we set the wrIdx above, and hence
  1035. // we may never get the threshold interrupt to serve the SRAM data we
  1036. // just wrote
  1037. // If that is the case, explicitly generate the FSIZE interrupt from here
  1038. fifoSize = AM_BFR(IOSLAVE, FIFOPTR, FIFOSIZ);
  1039. if ( fifoSize <= AM_BFR(IOSLAVE, FIFOTHR, FIFOTHR) )
  1040. {
  1041. AM_BFW(IOSLAVE, INTSET, FSIZE, 1);
  1042. }
  1043. }
  1044. // Number of bytes written
  1045. g_sSRAMBuffer.ui32FifoInc += totalBytes - ui32NumBytes;
  1046. return (totalBytes - ui32NumBytes);
  1047. }
  1048. //*****************************************************************************
  1049. //
  1050. //! @brief Writes the specified number of bytes to the IOS fifo simply.
  1051. //!
  1052. //! @param pui8Data is a pointer to the data to be written to the fifo.
  1053. //! @param ui32NumBytes is the number of bytes to send.
  1054. //!
  1055. //! This function will write data from the caller-provided array to the IOS
  1056. //! LRAM FIFO. This simple routine does not use SRAM buffering for large
  1057. //! messages. This function also updates the FIFOCTR.
  1058. //!
  1059. //! The maximum message size for the IO Slave is 128 bytes.
  1060. //!
  1061. //! @note Do note call the \e am_hal_ios_buffer_service() function in the ISR for
  1062. //! the ioslave module.
  1063. //!
  1064. //! @return
  1065. //
  1066. //*****************************************************************************
  1067. void
  1068. am_hal_ios_fifo_write_simple(uint8_t *pui8Data, uint32_t ui32NumBytes)
  1069. {
  1070. uint32_t ui32FIFOSpace;
  1071. //
  1072. // Check the FIFO and the SRAM buffer to see where we have space.
  1073. //
  1074. ui32FIFOSpace = fifo_space_left();
  1075. //
  1076. // If the whole message fits, send it now.
  1077. //
  1078. if ( ui32NumBytes <= ui32FIFOSpace )
  1079. {
  1080. fifo_write(pui8Data, ui32NumBytes);
  1081. // Write FIFOINC
  1082. AM_BFW(IOSLAVE, FIFOINC, FIFOINC, ui32NumBytes);
  1083. }
  1084. else
  1085. {
  1086. //
  1087. // The message didn't fit. Try using am_hal_ios_fifo_write() instead.
  1088. //
  1089. am_hal_debug_assert_msg(0, "The requested IOS transfer didn't fit in"
  1090. "the LRAM FIFO. Try using am_hal_ios_fifo_write().");
  1091. }
  1092. }
  1093. //*****************************************************************************
  1094. //
  1095. //! @brief Sets the IOS FIFO pointer to the specified LRAM offset.
  1096. //!
  1097. //! @param ui32Offset is LRAM offset to set the FIFO pointer to.
  1098. //!
  1099. //! @return None.
  1100. //
  1101. //*****************************************************************************
  1102. void
  1103. am_hal_ios_fifo_ptr_set(uint32_t ui32Offset)
  1104. {
  1105. uint32_t ui32Primask;
  1106. //
  1107. // Start a critical section for thread safety.
  1108. //
  1109. ui32Primask = am_hal_interrupt_master_disable();
  1110. //
  1111. // Set the FIFO Update bit.
  1112. //
  1113. AM_REG(IOSLAVE, FUPD) = 0x1;
  1114. //
  1115. // Change the FIFO offset.
  1116. //
  1117. AM_REG(IOSLAVE, FIFOPTR) = ui32Offset;
  1118. //
  1119. // Clear the FIFO update bit.
  1120. //
  1121. AM_REG(IOSLAVE, FUPD) = 0x0;
  1122. //
  1123. // Set the global FIFO-pointer tracking variable.
  1124. //
  1125. g_pui8FIFOPtr = (uint8_t *) (REG_IOSLAVE_BASEADDR + ui32Offset);
  1126. //
  1127. // End the critical section.
  1128. //
  1129. am_hal_interrupt_master_set(ui32Primask);
  1130. }
  1131. //*****************************************************************************
  1132. //
  1133. // Initialize an SRAM buffer for use with the IO Slave.
  1134. //
  1135. //*****************************************************************************
  1136. static void
  1137. am_hal_ios_buffer_init(am_hal_ios_buffer_t *psBuffer, void *pvArray,
  1138. uint32_t ui32Bytes)
  1139. {
  1140. psBuffer->ui32WriteIndex = 0;
  1141. psBuffer->ui32ReadIndex = 0;
  1142. psBuffer->ui32Length = 0;
  1143. psBuffer->ui32Capacity = ui32Bytes;
  1144. psBuffer->ui32FifoInc = 0;
  1145. psBuffer->pui8Data = (uint8_t *)pvArray;
  1146. }
  1147. //*****************************************************************************
  1148. //
  1149. //! @brief Poll for all host side read activity to complete.
  1150. //!
  1151. //! Poll for all host side read activity to complete. Use this before
  1152. //! calling am_hal_ios_fifo_write_simple().
  1153. //!
  1154. //! @return None.
  1155. //
  1156. //*****************************************************************************
  1157. void
  1158. am_hal_ios_read_poll_complete(void)
  1159. {
  1160. while ( AM_REG(IOSLAVE, FUPD) & AM_REG_IOSLAVE_FUPD_IOREAD_M );
  1161. }
  1162. //*****************************************************************************
  1163. //
  1164. //! @brief Initializes an SRAM buffer for the IOS FIFO.
  1165. //!
  1166. //! @param pui8Buffer is the SRAM buffer that will be used for IOS fifo data.
  1167. //! @param ui32BufferSize is the size of the SRAM buffer.
  1168. //!
  1169. //! This function provides the IOS HAL functions with working memory for
  1170. //! managing outgoing IOS FIFO transactions. It needs to be called at least
  1171. //! once before am_hal_ios_fifo_write() may be used.
  1172. //!
  1173. //! The recommended buffer size for the IOS FIFO is 1024 bytes.
  1174. //!
  1175. //! @return None.
  1176. //
  1177. //*****************************************************************************
  1178. void
  1179. am_hal_ios_fifo_buffer_init(uint8_t *pui8Buffer, uint32_t ui32NumBytes)
  1180. {
  1181. //
  1182. // Initialize the global SRAM buffer
  1183. // Total size, which is SRAM Buffer plus the hardware FIFO needs to be
  1184. // limited to 1023
  1185. //
  1186. if ( ui32NumBytes > (1023 - g_ui32HwFifoSize + 1) )
  1187. {
  1188. ui32NumBytes = (1023 - g_ui32HwFifoSize + 1);
  1189. }
  1190. am_hal_ios_buffer_init(&g_sSRAMBuffer, pui8Buffer, ui32NumBytes);
  1191. //
  1192. // Clear the FIFO State
  1193. //
  1194. AM_BFW(IOSLAVE, FIFOCTR, FIFOCTR, 0x0);
  1195. AM_BFW(IOSLAVE, FIFOPTR, FIFOSIZ, 0x0);
  1196. am_hal_ios_fifo_ptr_set(g_ui32FifoBaseOffset);
  1197. }
  1198. //*****************************************************************************
  1199. //
  1200. //! @brief Update the FIFOCTR to inform host of available data to read.
  1201. //!
  1202. //! This function allows the application to indicate to HAL when it is safe to
  1203. //! update the FIFOCTR. This function needs to be used in conjunction with
  1204. //! am_hal_ios_fifo_write(), which itself does not update the FIFOCTR
  1205. //!
  1206. //! CAUTION:
  1207. //! Application needs to implement some sort of
  1208. //! synchronization with the host to make sure host is not reading FIFOCTR while
  1209. //! it is being updated by the MCU, since the FIFOCTR read over
  1210. //! IO is not an atomic operation. Otherwise, some other logic could be implemented
  1211. //! by the host to detect and disregard transient values of FIFOCTR (e.g. multiple
  1212. //! reads till it gets a stable value).
  1213. //! For Pre-B2 parts, it is necessary to have this synchronization guarantee that
  1214. //! Host is not doing any READ operation - be it for FIFOCTR or FIFO itself when
  1215. //! this call is made, as otherwise the FIFOCTR value may get corrupted.
  1216. //!
  1217. //!
  1218. //! @return None.
  1219. //
  1220. //*****************************************************************************
  1221. void
  1222. am_hal_ios_update_fifoctr(void)
  1223. {
  1224. // Write FIFOINC
  1225. AM_BFW(IOSLAVE, FIFOINC, FIFOINC, g_sSRAMBuffer.ui32FifoInc);
  1226. g_sSRAMBuffer.ui32FifoInc = 0;
  1227. return;
  1228. }
  1229. //*****************************************************************************
  1230. //
  1231. // End the doxygen group
  1232. //! @}
  1233. //
  1234. //*****************************************************************************