eeprom_drv.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #include "board.h"
  2. //static struct rt_event event_i2c1;
  3. //static uint8_t SlvAddrRWE;
  4. //static uint8_t *PtrBuf;
  5. //static int16_t BufLen;
  6. //static uint32_t PinSCL;
  7. //static uint32_t PinSDA;
  8. #define I2C1_CR_CFG ( \
  9. (1<<6) | /* ens, I2C module 0:off; 1:on; */ \
  10. (1<<0) /* hlm, 0:advance filter(TM must>9); 1:simple filter; */ \
  11. )
  12. #define I2C1_CR_START (1u<<5)
  13. #define I2C1_CR_STOP (1u<<4)
  14. #define I2C1_CR_SI (1u<<3)
  15. #define I2C1_CR_HOLD (1u<<3)
  16. #define I2C1_CR_NEXT (0u<<3)
  17. #define I2C1_CR_ACK (1u<<2)
  18. #define I2C1_CR_NACK (0u<<2)
  19. typedef enum i2c_stat_code{
  20. I2C_TX_START = 0x08u,
  21. I2C_TX_RESTART = 0x10u,
  22. I2C_TX_WADDR_ACK = 0x18u,
  23. I2C_TX_WADDR_NACK = 0x20u,
  24. I2C_TX_WDATA_ACK = 0x28u,
  25. I2C_TX_WDATA_NACK = 0x30u,
  26. I2C_TX_CLOCK_FAIL = 0x38u,
  27. I2C_TX_RADDR_ACK = 0x40u,
  28. I2C_TX_RADDR_NACK = 0x48u,
  29. I2C_RX_RDATA_ACK = 0x50u,
  30. I2C_RX_RDATA_NACK = 0x58u,
  31. I2C_RX_WADDR_ACK = 0x60u,
  32. I2C_RX_WADDR_ACK_M2S = 0x68u,
  33. I2C_RX_WDATA_ACK = 0x80u,
  34. I2C_RX_WDATA_NACK = 0x88u,
  35. I2C_RX_WEND = 0xA0u,
  36. I2C_RX_RADDR_ACK = 0xA8u,
  37. I2C_RX_RADDR_ACK_M2S = 0xB0u,
  38. I2C_TX_RDATA_ACK = 0xB8u,
  39. I2C_TX_RDATA_NACK = 0xC0u,
  40. } i2c_stat_code_t;
  41. // PD10: 1:power on; 0:power off;
  42. // PA15: write protect for EEPROM, 1: write forbid; 0:allow write;
  43. // PF07: I2C1_SDA
  44. // PF06: I2C1_SCL
  45. void eeprom_init(void) // for EEPROM(M24M01 128KByts) chip
  46. {
  47. // GpioSetPins(GpioPortD, GpioBitMsk10); // power on
  48. GpioClrPins(GpioPortD, GpioBitMsk10); // power off
  49. GpioInit(PD10_AF0, GPIO_DIG_OUT_WEAK_PUSH_NONEUP_NONEDOWN);
  50. // keep I2C1_WP same level as PIN_VCC_I2C for saving power
  51. // GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
  52. GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
  53. GpioInit(PA15_AF0, GPIO_DIG_OUT_WEAK_PUSH_NONEUP_NONEDOWN);
  54. PeriClk_MutEnable(PeriClk_I2c1);
  55. MutResetPeri(ResetI2c1); // not asynchronous reset, must be effective after enable clock
  56. // Fscl = Fpclk/8/(TM+1)
  57. #if defined(SYSCLK_4M_MODE)
  58. M0P_I2C1->TM = 0x1; // Fscl = 250KHz
  59. #elif defined(SYSCLK_8M_MODE)
  60. M0P_I2C1->TM = 0x1; // Fscl = 500KHz
  61. #elif defined(SYSCLK_16M_MODE)
  62. M0P_I2C1->TM = 0x3; // Fscl = 500KHz
  63. #endif
  64. M0P_I2C1->TMRUN = 0x1; // 0:Baud rate off; 1:Baud rate on;
  65. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_HOLD;
  66. PeriClk_MutDisable(PeriClk_I2c1);
  67. // EEPROM
  68. GpioInit(PF06_I2C1_SCL, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  69. GpioInit(PF07_I2C1_SDA, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  70. // // enable interrupt at NVIC side
  71. // IRQMutEnable(I2C1_IRQn, IRQnPriority3);
  72. }
  73. void i2c1_rescue(void)
  74. {
  75. int16_t i;
  76. GpioSetPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
  77. GpioSetPins(GpioPortF, GpioBitMsk7); // I2C1_SDA
  78. GpioInit(PF06_AF0, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  79. GpioInit(PF07_AF0, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  80. i = 10;
  81. while(i--){
  82. GpioClrPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
  83. GpioSetPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
  84. }
  85. GpioInit(PF06_I2C1_SCL, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  86. GpioInit(PF07_I2C1_SDA, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
  87. }
  88. // Len is for data only, address byte is not included
  89. uint8_t I2C1_RdWrPacket(uint8_t AddrRWE, uint8_t *Buf, uint16_t Len)
  90. {
  91. uint8_t i2c_next;
  92. uint8_t i2c_error;
  93. PeriClk_MutEnable(PeriClk_I2c1);
  94. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_START | I2C1_CR_NEXT;
  95. i2c_next = 0x1u;
  96. while(i2c_next){
  97. while((~M0P_I2C1->CR) & I2C1_CR_SI){
  98. // wait until SI=1
  99. }
  100. switch(M0P_I2C1->STAT){
  101. case(I2C_TX_START):
  102. case(I2C_TX_RESTART):
  103. M0P_I2C1->DATA = AddrRWE;
  104. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NEXT;
  105. break;
  106. case(I2C_TX_WADDR_ACK):
  107. case(I2C_TX_WDATA_ACK):
  108. if (Len<=0){
  109. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
  110. i2c_error = 0x0u;
  111. i2c_next = 0x0u;
  112. } else {
  113. Len--;
  114. M0P_I2C1->DATA = *(Buf++);
  115. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NEXT;
  116. }
  117. break;
  118. case(I2C_RX_RDATA_ACK):
  119. case(I2C_RX_RDATA_NACK):
  120. *(Buf++) = M0P_I2C1->DATA;
  121. case(I2C_TX_RADDR_ACK):
  122. if (Len<=0){
  123. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
  124. i2c_error = 0x0u;
  125. i2c_next = 0x0u;
  126. } else {
  127. if (Len==1){
  128. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NACK | I2C1_CR_NEXT;
  129. } else {
  130. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_ACK | I2C1_CR_NEXT;
  131. }
  132. Len--;
  133. }
  134. break;
  135. default:
  136. M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
  137. i2c_error = 0x1u;
  138. i2c_next = 0x0u;
  139. }
  140. }
  141. PeriClk_MutDisable(PeriClk_I2c1);
  142. if (i2c_error){
  143. return(0x1u); // fail
  144. } else {
  145. return(0x0u); // ok
  146. }
  147. }
  148. // NOTE: Page size is 256Bytes, so any write must not cross page boundary
  149. // size of Buf >= DLen+3 (Must)
  150. // Buf[0] is address A16
  151. // Buf[1] is address A15-A8
  152. // Buf[2] is address A7-A0
  153. // Buf[3]~Buf[DLen+2] is WR data
  154. // DLen>=1, at least 1 WR data(be sure (A[7:0] + DLen) <=256)
  155. uint8_t EEPROM_WrPacket(uint8_t *Buf, uint16_t DLen)
  156. {
  157. uint8_t ret;
  158. uint8_t AddrRWE;
  159. GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
  160. GpioSetPins(GpioPortD, GpioBitMsk10); // power on
  161. AddrRWE = ((Buf[0]&0x01u)<<1) | 0xA0u;
  162. GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
  163. ret = I2C1_RdWrPacket(AddrRWE, Buf+1, DLen+2);
  164. GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
  165. //us_delay(5000); // tW = 5ms
  166. rt_thread_mdelay(5);
  167. // keep I2C1_WP same level as PIN_VCC_I2C for saving power
  168. GpioClrPins(GpioPortD, GpioBitMsk10); // power off
  169. GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
  170. return(ret);
  171. }
  172. // size of Buf >= DLen+3 (Must)
  173. // Buf[0] is address A16
  174. // Buf[1] is address A15-A8
  175. // Buf[2] is address A7-A0
  176. // Buf[3]~Buf[DLen+2] is RD data
  177. // DLen>=1, at least 1 WR data
  178. uint8_t EEPROM_RdPacket(uint8_t *Buf, uint16_t DLen)
  179. {
  180. uint8_t ret;
  181. uint8_t AddrRWE;
  182. GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
  183. GpioSetPins(GpioPortD, GpioBitMsk10); // power on
  184. AddrRWE = ((Buf[0]&0x01u)<<1) | 0xA0u;
  185. ret = I2C1_RdWrPacket(AddrRWE, Buf+1, 2);
  186. if (ret){
  187. return(ret);
  188. }
  189. AddrRWE |= 0x01u;
  190. ret = I2C1_RdWrPacket(AddrRWE, Buf+3, DLen);
  191. // keep I2C1_WP same level as PIN_VCC_I2C for saving power
  192. GpioClrPins(GpioPortD, GpioBitMsk10); // power off
  193. GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
  194. return(ret);
  195. }