i2c_slave.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /**************************************************************************************************
  2. Phyplus Microelectronics Limited confidential and proprietary.
  3. All rights reserved.
  4. IMPORTANT: All rights of this software belong to Phyplus Microelectronics
  5. Limited ("Phyplus"). Your use of this Software is limited to those
  6. specific rights granted under the terms of the business contract, the
  7. confidential agreement, the non-disclosure agreement and any other forms
  8. of agreements as a customer or a partner of Phyplus. You may not use this
  9. Software unless you agree to abide by the terms of these agreements.
  10. You acknowledge that the Software may not be modified, copied,
  11. distributed or disclosed unless embedded on a Phyplus Bluetooth Low Energy
  12. (BLE) integrated circuit, either as a product or is integrated into your
  13. products. Other than for the aforementioned purposes, you may not use,
  14. reproduce, copy, prepare derivative works of, modify, distribute, perform,
  15. display or sell this Software and/or its documentation for any purposes.
  16. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
  17. PROVIDED AS IS WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
  18. INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
  19. NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
  20. PHYPLUS OR ITS SUBSIDIARIES BE LIABLE OR OBLIGATED UNDER CONTRACT,
  21. NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
  22. LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
  23. INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
  24. OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
  25. OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
  26. (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
  27. **************************************************************************************************/
  28. /*******************************************************************************
  29. * @file i2c_slave.c
  30. * @brief i2c slave function
  31. * @version 1.0
  32. * Copyright(C) 2016, PhyPlus Semiconductor
  33. * All rights reserved.
  34. *******************************************************************************/
  35. /*******************************************************************************
  36. *@ Module : Includes
  37. *@ Description : NULL
  38. *******************************************************************************/
  39. #include "i2c_slave.h"
  40. #include "gpio.h"
  41. #include "error.h"
  42. #include "osal.h"
  43. #include "clock.h"
  44. #include "log.h"
  45. /*******************************************************************************
  46. *@ Module : IIC_Slave status
  47. *@ Description : NULL
  48. *******************************************************************************/
  49. typedef enum
  50. {
  51. Slave_Closed = 0,
  52. Slave_Opened,
  53. }IIC_Slave_status;
  54. /*******************************************************************************
  55. *@ Module : IIC_Slave_cfg structure
  56. *@ Description : NULL
  57. *******************************************************************************/
  58. typedef struct
  59. {
  60. AP_I2C_TypeDef *addr; // get by software
  61. MODULE_e module; // get by software
  62. uint8_t INTR_ID; // get by software
  63. GPIO_Pin_e SDA_PIN; // I2C Pin
  64. GPIO_Pin_e SCL_PIN;
  65. Fmux_Type_e Fmux_SCL; // get by software
  66. Fmux_Type_e Fmux_SDA; // get by software
  67. IIC_Slave_status state;
  68. }IIC_Slave_cfg;
  69. /*******************************************************************************
  70. *@ Module : Global Variable
  71. *@ Description : NULL
  72. *******************************************************************************/
  73. IIC_Slave_cfg Slave_cfg_g[IIC_COUNT];
  74. /*******************************************************************************
  75. *@ Module : Internal Function statement
  76. *@ Description : NULL
  77. *******************************************************************************/
  78. void I2C_Slave_Handler(I2C_Evt_t *pev);
  79. /*******************************************************************************
  80. *@ Module : Function Statement
  81. *@ Description : NULL
  82. *******************************************************************************/
  83. uint8_t Hal_I2C_Slave_Init(I2C_Slave_Parameter *para,uint8_t *handle)
  84. {
  85. uint8_t ret;
  86. LOG("Hal_I2C_Slave_Init wakeup id:%02X \r\n",para->id);
  87. ret = Hal_IIC_Valid_Check(para->id);
  88. if( ret == TRUE )
  89. {
  90. return PPLUS_ERR_IIC_BUSY;
  91. }
  92. else if( ret == PPlus_ERR_IIC_ID)
  93. {
  94. return PPlus_ERR_IIC_ID;
  95. }
  96. else
  97. {
  98. if( Hal_IIC_Addr_Valid(para->Slave_Address) != PPlus_IIC_SUCCESS)
  99. return PPlus_ERR_IIC_ADDRESS;
  100. osal_memset(&Slave_cfg_g[para->id],0,sizeof(IIC_Slave_cfg));
  101. // pre-para get
  102. Slave_cfg_g[para->id].addr = Hal_Get_IIC_Instance(para->id);
  103. Slave_cfg_g[para->id].module = Hal_GetIIC_ModuleID(para->id);
  104. Slave_cfg_g[para->id].INTR_ID = Hal_GetIIC_IRQID(para->id);
  105. Hal_GetIIC_PIN_Fmux(para->id,&(Slave_cfg_g[para->id].Fmux_SCL),&(Slave_cfg_g[para->id].Fmux_SDA));
  106. Slave_cfg_g[para->id].state = Slave_Closed;
  107. // io init
  108. Slave_cfg_g[para->id].SCL_PIN = para->SCL_PIN;
  109. Slave_cfg_g[para->id].SDA_PIN = para->SDA_PIN;
  110. hal_gpio_fmux_set(para->SCL_PIN, Slave_cfg_g[para->id].Fmux_SCL);
  111. hal_gpio_fmux_set(para->SDA_PIN, Slave_cfg_g[para->id].Fmux_SDA);
  112. hal_gpio_pull_set(para->SCL_PIN,STRONG_PULL_UP);
  113. hal_gpio_pull_set(para->SDA_PIN,STRONG_PULL_UP);
  114. // init
  115. clk_gate_enable(Slave_cfg_g[para->id].module);
  116. Slave_cfg_g[para->id].addr->IC_ENABLE = FALSE;
  117. Slave_cfg_g[para->id].addr->IC_CON = para->workmode | para->AddressMode;
  118. Slave_cfg_g[para->id].addr->IC_SAR = para->Slave_Address;
  119. Slave_cfg_g[para->id].addr->IC_RX_TL = para->RX_FIFO_Len - 1;
  120. Slave_cfg_g[para->id].addr->IC_TX_TL = para->Tx_FIFO_Len - 1;
  121. Slave_cfg_g[para->id].addr->IC_INTR_MASK = para->IRQ_Source;
  122. Hal_IIC_Register_CallBack(para->id,para->evt_handler);
  123. Hal_I2c_Slave_Open(para->id);
  124. // NVIC Config
  125. NVIC_EnableIRQ((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID));
  126. NVIC_SetPriority((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID), IRQ_PRIO_HAL);
  127. *handle = para->id;
  128. return PPlus_IIC_SUCCESS;
  129. }
  130. }
  131. /*******************************************************************************
  132. *@ Module : Open I2C Slave
  133. *@ Description : NULL
  134. *******************************************************************************/
  135. uint8_t Hal_I2c_Slave_Open(uint8_t handle)
  136. {
  137. if( Slave_cfg_g[handle].state == Slave_Closed )
  138. {
  139. Slave_cfg_g[handle].state = Slave_Opened;
  140. Slave_cfg_g[handle].addr->IC_ENABLE = TRUE;
  141. return PPlus_IIC_SUCCESS;
  142. }
  143. else
  144. return PPlus_ERR_IIC_FAILURE;
  145. }
  146. /*******************************************************************************
  147. *@ Module : Close I2C Slave
  148. *@ Description : NULL
  149. *******************************************************************************/
  150. void Hal_I2c_Slave_Close(uint8_t handle)
  151. {
  152. Slave_cfg_g[handle].addr->IC_ENABLE = FALSE;
  153. }
  154. /*******************************************************************************
  155. *@ Module : Close I2C Slave
  156. *@ Description : Should check close states,if closed completed
  157. a delay occurs when IC_ENABLE is set to 0, because close iic module depends
  158. on the iic bus activity
  159. *******************************************************************************/
  160. uint8_t Hal_Check_I2C_Slave_Closed(uint8_t handle)
  161. {
  162. if( Hal_Check_IIC_Closed(Slave_cfg_g[handle].addr) == PPlus_IIC_SUCCESS )
  163. {
  164. Slave_cfg_g[handle].state = Slave_Closed;
  165. return PPlus_IIC_SUCCESS;
  166. }
  167. else
  168. return PPLUS_ERR_IIC_ENABLE;
  169. }
  170. /*******************************************************************************
  171. *@ Module : Close I2C Slave
  172. *@ Description : NULL
  173. *******************************************************************************/
  174. uint8_t Hal_I2C_Slave_Deinit(uint8_t *handle)
  175. {
  176. LOG("HAL I2C SLAVE DINIT handle Value %d \n",*handle);
  177. if( Hal_IIC_unRegister_CallBack(*handle) != PPlus_IIC_SUCCESS )
  178. return PPlus_ERR_IIC_FAILURE;
  179. // // NVIC Config -- Disable
  180. // NVIC_DisableIRQ((IRQn_Type)(Slave_cfg_g[*handle].INTR_ID));
  181. //
  182. // // clock disable
  183. // clk_gate_disable( Slave_cfg_g[*handle].module);
  184. //
  185. // // io deinit
  186. // hal_gpio_fmux(Slave_cfg_g[*handle].SCL_PIN,Bit_DISABLE);
  187. // hal_gpio_fmux(Slave_cfg_g[*handle].SDA_PIN,Bit_DISABLE);
  188. // hal_gpio_pull_set(Slave_cfg_g[*handle].SCL_PIN,PULL_DOWN);
  189. // hal_gpio_pull_set(Slave_cfg_g[*handle].SDA_PIN,PULL_DOWN);
  190. //
  191. // osal_memset(&Slave_cfg_g[*handle],0,sizeof(IIC_Slave_cfg));
  192. *handle = PPlus_INVALID_HANDLE;
  193. return PPlus_IIC_SUCCESS;
  194. }
  195. /*******************************************************************************
  196. *@ Module : Read data from rx fifo
  197. *@ Description : NULL
  198. *******************************************************************************/
  199. void Hal_I2C_Slave_ReadRX_FIFO(uint8_t handle,uint8_t *p,uint8_t len)
  200. {
  201. for(uint8_t i =0;i<len;i++)
  202. *p++ = Hal_IIC_Read_RXFIFO(Slave_cfg_g[handle].addr);
  203. }
  204. /*******************************************************************************
  205. *@ Module : Clear interrupt status
  206. *@ Description : NULL
  207. *******************************************************************************/
  208. void Hal_I2C_Slave_CLR_IRQs(uint8_t handle,uint32_t irqs)
  209. {
  210. Hal_INTR_SOURCE_Clear(Slave_cfg_g[handle].addr,irqs);
  211. }
  212. /*******************************************************************************
  213. *@ Module : Hal_I2C_Slave_WriteTX_FIFO
  214. *@ Description : NULL
  215. *******************************************************************************/
  216. void Hal_I2C_Slave_WriteTX_FIFO(uint8_t handle,uint8_t *p,uint8_t len)
  217. {
  218. for(uint8_t i=0;i<len;i++)
  219. Hal_IIC_Write_TXFIFO(Slave_cfg_g[handle].addr,*p++);
  220. }
  221. /*******************************************************************************
  222. *@ Module : I2C Slave Init steps:
  223. *@ Description : NULL
  224. *******************************************************************************/
  225. /*
  226. 1、IC_ENABLE=0;
  227. 2、IC_SAR = ? (Master和Slave不能设置相同的地址类型?)
  228. 3、IC_CON(配置地址模式和SLAVE模式)
  229. 4、IC_ENABLE=1;
  230. */
  231. /*******************************************************************************
  232. *@ Module : I2C Slave 单字节发送
  233. *@ Description : NULL
  234. *******************************************************************************/
  235. /*
  236. 1、IIC MASTER 寻址
  237. 2、IIC SLAVE ACK
  238. 3、IIC SLAVE 触发 RD_REQ 中断, 同时 HOLD THE SCL LOW , WAIT UNTIL THE SOFTWARE RESPONDS(数据响应?)
  239. SOFTWARE RESPONDS的时间间隔,10倍SCL周期 (400K--->25us)(一个byte传输完成的时间)
  240. 4、读请求触发前,如果TXFIFO,总线触发TX_ABRT中断,清除旧数据 (通过软件读取 IC_CLR_TX_ABRT register,释放总线)
  241. 5、写数据到 IC_DATA_CMD
  242. 6、清除RD_REQ,TX_ABRT中断标志位(如果中断被屏蔽,则需要清除IC_RAW_INTR_STAT)
  243. 7、总线释放SCL并传输数据(与2对应)
  244. 8、MASTER 通过RESTART 或 STOP 继续操作总线
  245. */
  246. /*******************************************************************************
  247. *@ Module : I2C Slave 单字节接收
  248. *@ Description : NULL
  249. *******************************************************************************/
  250. /*
  251. 1、IIC MASTER 寻址
  252. 2、IIC SLAVE ACK
  253. 3、receives the transmitted byte and places it in the receive buffer
  254. 如果RX FIFO已经满了,再来数据的时候,将会触发R_RX_OVER中断,于此同时,
  255. IIC数据将会继续传输(没有NACK信号),并无法保证后续数据的完整
  256. 4、RX_FULL 中断
  257. 5、从IC_DATA_CMD 中读取数据
  258. 6、MASTER 通过RESTART 或 STOP 继续操作总线
  259. */