hv_drv_GpioSimI2c.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /**
  2. * @file hv_drv_GpioSmutI2c.c
  3. * @brief gpio smulitaion i2c driver layer file.
  4. * @details This file provides the following functions: \n
  5. * (1) gpio simulate i2c master tx/rx \n
  6. * (2) gpio simulate i2c init \n
  7. *
  8. * @author HiView SoC Software Team
  9. * @version 1.0.0
  10. * @date 2023-06-06
  11. * @copyright Copyright(c),2023-6, Hiview Software. All rights reserved.
  12. * @par History:
  13. * <table>
  14. * <tr><th>Author <th>Date <th>Change Description
  15. * </table>
  16. */
  17. #include "Common/hv_comm_DataType.h"
  18. #include "Common/Assert/hv_comm_Assert.h"
  19. #include "hv_comm_Define.h"
  20. #include "hv_cal_Gpio.h"
  21. #include "hv_vos_Comm.h"
  22. #include "hv_drv_GpioSimI2c.h"
  23. static GpioSimI2c s_stgpiosimi2c[SIMI2CMAX-SIMI2C0] = {
  24. {INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8},
  25. {INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8},
  26. {INVALID_PARAM_UHCAR8, INVALID_PARAM_UHCAR8}
  27. };
  28. #define SET_SCL_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_DIR_OUTPUT)
  29. #define SET_SCL_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_DIR_INPUT)
  30. #define SET_SDA_OUT(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_DIR_OUTPUT)
  31. #define SET_SDA_IN(uiIndex) Hv_Cal_Gpio_SetDirection(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_DIR_INPUT)
  32. #define SET_SCL_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_LEVEL_HIGH)
  33. #define SET_SCL_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSclPin, GPIO_LEVEL_LOW)
  34. #define SET_SDA_HIGH(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_LEVEL_HIGH)
  35. #define SET_SDA_LOW(uiIndex) Hv_Cal_Gpio_SetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin, GPIO_LEVEL_LOW)
  36. #define GET_SDA_LEVEL(uiIndex) Hv_Cal_Gpio_GetPinLevel(s_stgpiosimi2c[uiIndex].ucSdaPin)
  37. #define GPIOSIMI2C_DELAY 2U
  38. #define GPIOSIMI2C_WAIT_ACK_TIMES 200U
  39. #define GPIOSIMI2C_ADDR_WRITE 0x00
  40. #define GPIOSIMI2C_ADDR_READ 0x01
  41. /** Initialize i2c
  42. * @param pstInitParam pointer to i2c configuration parameters
  43. * @return SUCCESS/FAILURE
  44. */
  45. Status Hv_Drv_GpioSimI2c_Init(I2cBusID enBus, const GpioSimI2c *pstGpioSimI2c)
  46. {
  47. HV_ASSERT_VALID_PTR_RET(pstGpioSimI2c, HV_FAILURE);
  48. if (enBus < SIMI2C0)
  49. {
  50. return HV_FAILURE;
  51. }
  52. UINT32 uiIndex = enBus - SIMI2C0;
  53. memcpy(&s_stgpiosimi2c[uiIndex], pstGpioSimI2c, sizeof(GpioSimI2c));
  54. SET_SCL_OUT(uiIndex);
  55. SET_SDA_OUT(uiIndex);
  56. SET_SCL_HIGH(uiIndex);
  57. SET_SDA_HIGH(uiIndex);
  58. return HV_SUCCESS;
  59. }
  60. /** I2c start signal
  61. *@SCL keep high, SDA change from high to low
  62. */
  63. static VOID Hv_GpioSimI2c_Start(UINT32 uiIndex)
  64. {
  65. SET_SDA_OUT(uiIndex);
  66. SET_SCL_HIGH(uiIndex);
  67. SET_SDA_HIGH(uiIndex);
  68. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  69. SET_SDA_LOW(uiIndex);
  70. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  71. SET_SCL_LOW(uiIndex);
  72. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  73. }
  74. /** I2c stop signal
  75. *@SCL keep high, SDA change from low to high
  76. */
  77. static VOID Hv_GpioSimI2c_Stop(UINT32 uiIndex)
  78. {
  79. SET_SDA_OUT(uiIndex);
  80. SET_SDA_LOW(uiIndex);
  81. SET_SCL_LOW(uiIndex);
  82. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  83. SET_SCL_HIGH(uiIndex);
  84. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  85. SET_SDA_HIGH(uiIndex);
  86. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  87. }
  88. /** master wait Ack signal
  89. *@Pull up SCL high, to read SDA level high or low
  90. */
  91. static Status Hv_GpioSimI2c_Wait_Ack(UINT32 uiIndex)
  92. {
  93. UINT32 uiWaitTime = 0;
  94. SET_SDA_IN(uiIndex);
  95. SET_SCL_LOW(uiIndex);
  96. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  97. SET_SCL_HIGH(uiIndex);
  98. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  99. while (GET_SDA_LEVEL(uiIndex))
  100. {
  101. if (uiWaitTime > GPIOSIMI2C_WAIT_ACK_TIMES)
  102. {
  103. Hv_GpioSimI2c_Stop(uiIndex);
  104. HV_LOGW("wait ack timeout!\n");
  105. return HV_FAILURE;
  106. }
  107. uiWaitTime++;
  108. }
  109. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  110. SET_SCL_LOW(uiIndex);
  111. return HV_SUCCESS;
  112. }
  113. /** send Ack signal
  114. *@SCL keep high, SDA create a valid low level
  115. */
  116. static VOID Hv_GpioSimI2c_Send_Ack(UINT32 uiIndex)
  117. {
  118. SET_SDA_OUT(uiIndex);
  119. SET_SCL_LOW(uiIndex);
  120. SET_SDA_LOW(uiIndex);
  121. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  122. SET_SCL_HIGH(uiIndex);
  123. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  124. SET_SCL_LOW(uiIndex);
  125. }
  126. /** send NAck signal
  127. *@SCL keep high, SDA create a valid high level
  128. */
  129. static VOID Hv_GpioSimI2c_Send_Nack(UINT32 uiIndex)
  130. {
  131. SET_SDA_OUT(uiIndex);
  132. SET_SCL_LOW(uiIndex);
  133. SET_SDA_HIGH(uiIndex);
  134. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  135. SET_SCL_HIGH(uiIndex);
  136. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  137. SET_SCL_LOW(uiIndex);
  138. }
  139. /** send data 1 byte
  140. *@ Send data bit by bit and MSB first;
  141. *@ When SCL keep high, data is valid;
  142. *@ when SCL change to low, SDA permited to change.
  143. */
  144. static VOID Hv_GpioSimI2c_Write_Byte(UINT32 uiIndex, UCHAR8 ucByte)
  145. {
  146. UCHAR8 ucStep = 0;
  147. SET_SDA_OUT(uiIndex);
  148. SET_SCL_LOW(uiIndex);
  149. for (ucStep = 0;ucStep < 8; ucStep++)
  150. {
  151. if ((ucByte<<ucStep)&0x80)
  152. {
  153. SET_SDA_HIGH(uiIndex);
  154. }
  155. else
  156. {
  157. SET_SDA_LOW(uiIndex);
  158. }
  159. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  160. SET_SCL_HIGH(uiIndex);
  161. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  162. SET_SCL_LOW(uiIndex);
  163. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  164. }
  165. }
  166. /** receive 1 byte
  167. *@Pull SCL high, to read SDA data from slave device bit by bit
  168. */
  169. static UCHAR8 Hv_GpioSimI2c_Read_Byte(UINT32 uiIndex)
  170. {
  171. UCHAR8 ucByte = 0x00;
  172. UCHAR8 ucStep = 0;
  173. SET_SDA_IN(uiIndex);
  174. for (ucStep = 0; ucStep < 8; ucStep++)
  175. {
  176. SET_SCL_LOW(uiIndex);
  177. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  178. SET_SCL_HIGH(uiIndex);
  179. ucByte = ucByte<<1;
  180. if (GET_SDA_LEVEL(uiIndex))
  181. {
  182. ucByte = ucByte | 0x01;
  183. }
  184. Hv_Vos_Delayus(GPIOSIMI2C_DELAY);
  185. }
  186. SET_SCL_LOW(uiIndex);
  187. return ucByte;
  188. }
  189. /** Send in master mode an amount of data
  190. * @param ucDevAddr target device address
  191. * @param pucRegAddr pointer to register address
  192. * @param usRegAddrSize register address length
  193. * @param pucData pointer to data buffer to be transmited
  194. * @param usDataSize amount of data to be sent
  195. * @retval Status SUCESS/FAILURE
  196. */
  197. Status Hv_Drv_GpioSimI2c_SendData(I2cBusID enBus, UCHAR8 ucDevAddr, UCHAR8 *pucRegAddr,
  198. USHORT16 usRegAddrSize, UCHAR8 *pcData, UINT32 uiDatasize)
  199. {
  200. if (enBus < SIMI2C0)
  201. {
  202. return HV_FAILURE;
  203. }
  204. UINT32 uiSize = 0;
  205. UINT32 uiIndex = enBus - SIMI2C0;
  206. //Start
  207. Hv_GpioSimI2c_Start(uiIndex);
  208. //Write write device addr
  209. Hv_GpioSimI2c_Write_Byte(uiIndex, ucDevAddr + GPIOSIMI2C_ADDR_WRITE);
  210. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  211. //Write register addr
  212. for (uiSize = 0; uiSize < usRegAddrSize; uiSize++)
  213. {
  214. Hv_GpioSimI2c_Write_Byte(uiIndex, pucRegAddr[uiSize]);
  215. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  216. }
  217. //Write Data
  218. for (uiSize = 0; uiSize < uiDatasize; uiSize++)
  219. {
  220. Hv_GpioSimI2c_Write_Byte(uiIndex, pcData[uiSize]);
  221. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  222. }
  223. //Stop
  224. Hv_GpioSimI2c_Stop(uiIndex);
  225. return HV_SUCCESS;
  226. }
  227. /** Receive in master mode an amount of data
  228. * @param ucDevAddr target device address
  229. * @param pucRegAddr pointer to register address
  230. * @param usRegAddrSize register address length
  231. * @param pucData pointer to data buffer to be transmited
  232. * @param usDataSize amount of data to be receive
  233. * @retval Status SUCESS/FAILURE
  234. */
  235. Status Hv_Drv_GpioSimI2c_RecvData(I2cBusID enBus, UCHAR8 ucDevAddr, UCHAR8 *pucRegAddr,
  236. USHORT16 usRegAddrSize, UCHAR8 *pucData, USHORT16 usDataSize)
  237. {
  238. if (enBus < SIMI2C0)
  239. {
  240. return HV_FAILURE;
  241. }
  242. UINT32 uiSize = 0;
  243. UINT32 uiIndex = enBus - SIMI2C0;
  244. //Start
  245. Hv_GpioSimI2c_Start(uiIndex);
  246. //Write write device addr
  247. Hv_GpioSimI2c_Write_Byte(uiIndex, ucDevAddr + GPIOSIMI2C_ADDR_WRITE);
  248. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  249. //Write register addr
  250. for (uiSize = 0; uiSize < usRegAddrSize; uiSize++)
  251. {
  252. Hv_GpioSimI2c_Write_Byte(uiIndex, pucRegAddr[uiSize]);
  253. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  254. }
  255. //Start
  256. Hv_GpioSimI2c_Start(uiIndex);
  257. //Write read device addr
  258. Hv_GpioSimI2c_Write_Byte(uiIndex, ucDevAddr + GPIOSIMI2C_ADDR_READ);
  259. HV_ASSERT_SUCCESS_RET(Hv_GpioSimI2c_Wait_Ack(uiIndex), HV_FAILURE);
  260. for (uiSize = 0; uiSize < usDataSize; uiSize++)
  261. {
  262. pucData[uiSize] = Hv_GpioSimI2c_Read_Byte(uiIndex);
  263. if (usDataSize && ((usDataSize - 1) == uiSize))//last one byte, Nack
  264. {
  265. Hv_GpioSimI2c_Send_Nack(uiIndex);
  266. }
  267. else
  268. {
  269. Hv_GpioSimI2c_Send_Ack(uiIndex);
  270. }
  271. }
  272. //Stop
  273. Hv_GpioSimI2c_Stop(uiIndex);
  274. return HV_SUCCESS;
  275. }