cmem7_i2c.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /**
  2. *****************************************************************************
  3. * @file cmem7_i2c.c
  4. *
  5. * @brief CMEM7 I2C source file
  6. *
  7. *
  8. * @version V1.0
  9. * @date 3. September 2013
  10. *
  11. * @note
  12. *
  13. *****************************************************************************
  14. * @attention
  15. *
  16. * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  17. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  18. * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
  19. * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  20. * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  21. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  22. *
  23. * <h2><center>&copy; COPYRIGHT 2013 Capital-micro </center></h2>
  24. *****************************************************************************
  25. */
  26. #include "cmem7_i2c.h"
  27. #define I2C_INNER_INT_ALL 0x3FF
  28. typedef struct {
  29. union {
  30. uint32_t DATA_CMD;
  31. struct {
  32. uint32_t DATA : 8;
  33. uint32_t RD_CMD : 1;
  34. uint32_t WR_CMD : 1;
  35. uint32_t WR_RD_CMD : 1;
  36. } DATA_CMD_b;
  37. } INNER;
  38. } I2C_INNER_DATA_CMD;
  39. static uint32_t i2c_GetClock(I2C0_Type* I2Cx) {
  40. uint32_t dividor;
  41. if ((uint32_t)I2Cx == (uint32_t)I2C0) {
  42. dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C0_CLK;
  43. } else if ((uint32_t)I2Cx == (uint32_t)I2C1) {
  44. dividor = GLOBAL_CTRL->CLK_SEL_0_b.I2C1_CLK;
  45. }
  46. return SYSTEM_CLOCK_FREQ / (1 << (dividor + 1));
  47. }
  48. static uint16_t i2c_NormalizeAddr(I2C0_Type* I2Cx, uint16_t addr) {
  49. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  50. if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
  51. if (I2Cx->CTRL_b.MASTER_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
  52. addr &= 0x007F;
  53. } else {
  54. addr &= 0x3FF;
  55. }
  56. }
  57. if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
  58. if (I2Cx->CTRL_b.SLAVE_ADDR_WIDTH == I2C_ADDR_WIDTH_7BIT) {
  59. addr &= 0x007F;
  60. } else {
  61. addr &= 0x3FF;
  62. }
  63. }
  64. return addr;
  65. }
  66. static void i2c_ReadClear(uint32_t bit) {
  67. uint32_t tmp;
  68. tmp = bit;
  69. tmp = tmp;
  70. }
  71. void I2C_Init(I2C0_Type* I2Cx, I2C_InitTypeDef* I2C_Init) {
  72. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  73. assert_param(I2C_Init);
  74. assert_param(IS_I2C_MODE(I2C_Init->I2C_Mode));
  75. assert_param(IS_I2C_ADDR_WIDTH(I2C_Init->I2C_AddressWidth));
  76. // reset
  77. I2Cx->ENABLE_b.RESET = FALSE;
  78. I2Cx->ENABLE_b.RESET = TRUE;
  79. // clear interrupt
  80. I2Cx->INT_MASK = I2C_INNER_INT_ALL;
  81. i2c_ReadClear(I2Cx->CLR_ALL_INT_b.CLEAR);
  82. I2Cx->CTRL_b.MODE = I2C_Init->I2C_Mode;
  83. if (I2Cx->CTRL_b.MODE == I2C_Mode_Master) {
  84. I2Cx->CTRL_b.MASTER_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
  85. I2Cx->TAR_b.START_BYTE = TRUE;
  86. I2Cx->TAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
  87. }
  88. if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
  89. I2Cx->CTRL_b.SLAVE_ADDR_WIDTH = I2C_Init->I2C_AddressWidth;
  90. I2Cx->SAR_b.ADDR10 = i2c_NormalizeAddr(I2Cx, I2C_Init->I2C_Address);
  91. }
  92. I2Cx->RX_TL_b.THRESHOLD = 0;
  93. I2Cx->TX_TL_b.THRESHOLD = 0;
  94. I2Cx->SLAVE_NACK_b.NACK = FALSE;
  95. if (I2C_Init->timing) {
  96. I2Cx->SCL_CNT_b.HIGH_LEVEL_TICK =
  97. i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
  98. I2Cx->SCL_CNT_b.LOW_LEVEL_TICK =
  99. i2c_GetClock(I2Cx) / I2C_Init->timing->I2C_Freq / 2;
  100. I2Cx->SDA_SETUP_b.TSU_DAT = ((uint64_t)I2C_Init->timing->I2C_TsuDat) *
  101. i2c_GetClock(I2Cx) / 1000000000;
  102. I2Cx->SDA_SETUP_b.TSETUP = ((uint64_t)I2C_Init->timing->I2C_Tsetup) *
  103. i2c_GetClock(I2Cx) / 1000000000;
  104. I2Cx->TSU_STA_SETUP_b.TBUF = ((uint64_t)I2C_Init->timing->I2C_Tbuf) *
  105. i2c_GetClock(I2Cx) / 1000000000;
  106. I2Cx->TSU_STA_SETUP_b.TSU_STA = ((uint64_t)I2C_Init->timing->I2C_TsuSta) *
  107. i2c_GetClock(I2Cx) / 1000000000;
  108. I2Cx->TSU_STA_SETUP_b.SDA_FILTER_EN = I2C_Init->timing->I2C_SdaFilterEn;
  109. I2Cx->TSU_STA_SETUP_b.SDA_FILTER_CNT = I2C_Init->timing->I2C_SdaFilterSpike;
  110. I2Cx->TSU_STA_SETUP_b.SCL_FILTER_EN = I2C_Init->timing->I2C_SclFilterEn;
  111. I2Cx->TSU_STA_SETUP_b.SCL_FILTER_CNT = I2C_Init->timing->I2C_SclFilterSpike;
  112. }
  113. }
  114. void I2C_Enable(I2C0_Type* I2Cx, BOOL enable) {
  115. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  116. I2Cx->ENABLE_b.EN = enable;
  117. }
  118. void I2C_EnableInt(I2C0_Type* I2Cx, uint32_t Int, BOOL enable) {
  119. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  120. assert_param(IS_I2C_INT(Int));
  121. if (enable) {
  122. I2Cx->INT_MASK &= ~Int;
  123. } else {
  124. I2Cx->INT_MASK |= Int;
  125. }
  126. }
  127. BOOL I2C_GetIntStatus(I2C0_Type* I2Cx, uint32_t Int) {
  128. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  129. assert_param(IS_I2C_INT(Int));
  130. if (0 != (I2Cx->INT_STATUS & Int)) {
  131. return TRUE;
  132. }
  133. return FALSE;
  134. }
  135. void I2C_ClearInt(I2C0_Type* I2Cx, uint32_t Int) {
  136. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  137. assert_param(IS_I2C_INT(Int));
  138. if (Int == I2C_INT_RX_FIFO_NOT_EMPTY) {
  139. // It can't be clear by sw but read data
  140. }
  141. if (Int == I2C_INT_RD_REQUEST) {
  142. i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
  143. }
  144. if (Int == I2C_INT_TX_ABORT) {
  145. i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
  146. }
  147. if (Int == I2C_INT_RX_DONE) {
  148. i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
  149. }
  150. if (Int == I2C_INT_TX_DONE) {
  151. i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
  152. }
  153. }
  154. BOOL I2C_GetStatus(I2C0_Type* I2Cx, uint32_t Status) {
  155. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  156. assert_param(IS_I2C_STATUS(Status));
  157. if (0 != (I2Cx->STATUS & Status)) {
  158. return TRUE;
  159. }
  160. return FALSE;
  161. }
  162. void I2C_ClearStatus(I2C0_Type* I2Cx, uint32_t Status) {
  163. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  164. assert_param(IS_I2C_STATUS(Status));
  165. if (Status & I2C_STATUS_RX_FIFO_NOT_EMPTY) {
  166. // It can't be clear by sw but read
  167. }
  168. if (Status & I2C_STATUS_RD_REQUEST) {
  169. i2c_ReadClear(I2Cx->CLR_RD_REQ_b.CLEAR);
  170. }
  171. if (Status & I2C_STATUS_TX_ABORT) {
  172. i2c_ReadClear(I2Cx->CLR_TX_ABRT_b.CLEAR);
  173. }
  174. if (Status & I2C_STATUS_RX_DONE) {
  175. i2c_ReadClear(I2Cx->CLR_RX_DONE_b.CLEAR);
  176. }
  177. if (Status & I2C_STATUS_TX_DONE) {
  178. i2c_ReadClear(I2Cx->CLR_TX_DONE_b.CLEAR);
  179. }
  180. }
  181. BOOL I2C_MasterReadReq(I2C0_Type* I2Cx, uint8_t size) {
  182. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  183. if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
  184. return FALSE;
  185. }
  186. if (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) {
  187. return FALSE;
  188. }
  189. if (size == 0) {
  190. return FALSE;
  191. }
  192. I2Cx->WRITE_READ_CNT_b.RD_BYTE_CNT = size;
  193. if (size != 0) {
  194. I2C_INNER_DATA_CMD inner;
  195. inner.INNER.DATA_CMD_b.DATA = 0;
  196. inner.INNER.DATA_CMD_b.RD_CMD = TRUE;
  197. inner.INNER.DATA_CMD_b.WR_CMD = FALSE;
  198. inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
  199. I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
  200. }
  201. return TRUE;
  202. }
  203. uint8_t I2C_ReadFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
  204. uint8_t count;
  205. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  206. assert_param(data);
  207. if (!I2Cx->ENABLE_b.EN) {
  208. return 0;
  209. }
  210. count = 0;
  211. while (I2Cx->STATUS_b.RX_FIFO_NOT_EMPTY && count < size) {
  212. *(data + count++) = I2Cx->DATA_CMD_b.DATA;
  213. }
  214. return count;
  215. }
  216. BOOL I2C_WriteReq(I2C0_Type* I2Cx, uint8_t size, uint8_t firstData) {
  217. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  218. if (!I2Cx->ENABLE_b.EN || I2Cx->STATUS_b.BUSY) {
  219. return FALSE;
  220. }
  221. if (size == 0) {
  222. return FALSE;
  223. }
  224. I2Cx->WRITE_READ_CNT_b.WR_BYTE_CNT = size;
  225. if (size != 0) {
  226. I2C_INNER_DATA_CMD inner;
  227. inner.INNER.DATA_CMD_b.DATA = firstData ;
  228. inner.INNER.DATA_CMD_b.RD_CMD = FALSE;
  229. inner.INNER.DATA_CMD_b.WR_CMD =
  230. (I2Cx->CTRL_b.MODE == I2C_Mode_Slave) ? FALSE : TRUE;
  231. inner.INNER.DATA_CMD_b.WR_RD_CMD = FALSE;
  232. I2Cx->DATA_CMD = inner.INNER.DATA_CMD;
  233. }
  234. return TRUE;
  235. }
  236. uint8_t I2C_WriteFifo(I2C0_Type* I2Cx, uint8_t size, uint8_t* data) {
  237. uint8_t count;
  238. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  239. assert_param(data);
  240. if (!I2Cx->ENABLE_b.EN) {
  241. return 0;
  242. }
  243. count = 0;
  244. while (I2Cx->STATUS_b.TX_FIFO_NOT_FULL && count < size) {
  245. I2Cx->DATA_CMD_b.DATA = *(data + count++);
  246. }
  247. return count;
  248. }
  249. BOOL I2C_StopReq(I2C0_Type* I2Cx) {
  250. assert_param(IS_I2C_ALL_PERIPH(I2Cx));
  251. udelay(600);
  252. return TRUE;
  253. }