| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- #include "board.h"
- //static struct rt_event event_i2c1;
- //static uint8_t SlvAddrRWE;
- //static uint8_t *PtrBuf;
- //static int16_t BufLen;
- //static uint32_t PinSCL;
- //static uint32_t PinSDA;
- #define I2C1_CR_CFG ( \
- (1<<6) | /* ens, I2C module 0:off; 1:on; */ \
- (1<<0) /* hlm, 0:advance filter(TM must>9); 1:simple filter; */ \
- )
- #define I2C1_CR_START (1u<<5)
- #define I2C1_CR_STOP (1u<<4)
- #define I2C1_CR_SI (1u<<3)
- #define I2C1_CR_HOLD (1u<<3)
- #define I2C1_CR_NEXT (0u<<3)
- #define I2C1_CR_ACK (1u<<2)
- #define I2C1_CR_NACK (0u<<2)
- typedef enum i2c_stat_code{
- I2C_TX_START = 0x08u,
- I2C_TX_RESTART = 0x10u,
- I2C_TX_WADDR_ACK = 0x18u,
- I2C_TX_WADDR_NACK = 0x20u,
- I2C_TX_WDATA_ACK = 0x28u,
- I2C_TX_WDATA_NACK = 0x30u,
- I2C_TX_CLOCK_FAIL = 0x38u,
- I2C_TX_RADDR_ACK = 0x40u,
- I2C_TX_RADDR_NACK = 0x48u,
- I2C_RX_RDATA_ACK = 0x50u,
- I2C_RX_RDATA_NACK = 0x58u,
- I2C_RX_WADDR_ACK = 0x60u,
- I2C_RX_WADDR_ACK_M2S = 0x68u,
- I2C_RX_WDATA_ACK = 0x80u,
- I2C_RX_WDATA_NACK = 0x88u,
- I2C_RX_WEND = 0xA0u,
- I2C_RX_RADDR_ACK = 0xA8u,
- I2C_RX_RADDR_ACK_M2S = 0xB0u,
- I2C_TX_RDATA_ACK = 0xB8u,
- I2C_TX_RDATA_NACK = 0xC0u,
- } i2c_stat_code_t;
- // PD10: 1:power on; 0:power off;
- // PA15: write protect for EEPROM, 1: write forbid; 0:allow write;
- // PF07: I2C1_SDA
- // PF06: I2C1_SCL
- void eeprom_init(void) // for EEPROM(M24M01 128KByts) chip
- {
- // GpioSetPins(GpioPortD, GpioBitMsk10); // power on
- GpioClrPins(GpioPortD, GpioBitMsk10); // power off
- GpioInit(PD10_AF0, GPIO_DIG_OUT_WEAK_PUSH_NONEUP_NONEDOWN);
-
- // keep I2C1_WP same level as PIN_VCC_I2C for saving power
- // GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
- GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
- GpioInit(PA15_AF0, GPIO_DIG_OUT_WEAK_PUSH_NONEUP_NONEDOWN);
- PeriClk_MutEnable(PeriClk_I2c1);
- MutResetPeri(ResetI2c1); // not asynchronous reset, must be effective after enable clock
- // Fscl = Fpclk/8/(TM+1)
- #if defined(SYSCLK_4M_MODE)
- M0P_I2C1->TM = 0x1; // Fscl = 250KHz
- #elif defined(SYSCLK_8M_MODE)
- M0P_I2C1->TM = 0x1; // Fscl = 500KHz
- #elif defined(SYSCLK_16M_MODE)
- M0P_I2C1->TM = 0x3; // Fscl = 500KHz
- #endif
- M0P_I2C1->TMRUN = 0x1; // 0:Baud rate off; 1:Baud rate on;
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_HOLD;
- PeriClk_MutDisable(PeriClk_I2c1);
- // EEPROM
- GpioInit(PF06_I2C1_SCL, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- GpioInit(PF07_I2C1_SDA, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- // // enable interrupt at NVIC side
- // IRQMutEnable(I2C1_IRQn, IRQnPriority3);
- }
- void i2c1_rescue(void)
- {
- int16_t i;
- GpioSetPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
- GpioSetPins(GpioPortF, GpioBitMsk7); // I2C1_SDA
- GpioInit(PF06_AF0, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- GpioInit(PF07_AF0, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- i = 10;
- while(i--){
- GpioClrPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
- GpioSetPins(GpioPortF, GpioBitMsk6); // I2C1_SCL
- }
- GpioInit(PF06_I2C1_SCL, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- GpioInit(PF07_I2C1_SDA, GPIO_DIG_OUT_WEAK_OPEN_NONEUP_NONEDOWN); // set pin to output open
- }
- // Len is for data only, address byte is not included
- uint8_t I2C1_RdWrPacket(uint8_t AddrRWE, uint8_t *Buf, uint16_t Len)
- {
- uint8_t i2c_next;
- uint8_t i2c_error;
- PeriClk_MutEnable(PeriClk_I2c1);
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_START | I2C1_CR_NEXT;
- i2c_next = 0x1u;
- while(i2c_next){
- while((~M0P_I2C1->CR) & I2C1_CR_SI){
- // wait until SI=1
- }
- switch(M0P_I2C1->STAT){
- case(I2C_TX_START):
- case(I2C_TX_RESTART):
- M0P_I2C1->DATA = AddrRWE;
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NEXT;
- break;
- case(I2C_TX_WADDR_ACK):
- case(I2C_TX_WDATA_ACK):
- if (Len<=0){
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
- i2c_error = 0x0u;
- i2c_next = 0x0u;
- } else {
- Len--;
- M0P_I2C1->DATA = *(Buf++);
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NEXT;
- }
- break;
- case(I2C_RX_RDATA_ACK):
- case(I2C_RX_RDATA_NACK):
- *(Buf++) = M0P_I2C1->DATA;
- case(I2C_TX_RADDR_ACK):
- if (Len<=0){
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
- i2c_error = 0x0u;
- i2c_next = 0x0u;
- } else {
- if (Len==1){
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_NACK | I2C1_CR_NEXT;
- } else {
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_ACK | I2C1_CR_NEXT;
- }
- Len--;
- }
- break;
- default:
- M0P_I2C1->CR = I2C1_CR_CFG | I2C1_CR_STOP | I2C1_CR_NEXT;
- i2c_error = 0x1u;
- i2c_next = 0x0u;
- }
- }
- PeriClk_MutDisable(PeriClk_I2c1);
- if (i2c_error){
- return(0x1u); // fail
- } else {
- return(0x0u); // ok
- }
- }
- // NOTE: Page size is 256Bytes, so any write must not cross page boundary
- // size of Buf >= DLen+3 (Must)
- // Buf[0] is address A16
- // Buf[1] is address A15-A8
- // Buf[2] is address A7-A0
- // Buf[3]~Buf[DLen+2] is WR data
- // DLen>=1, at least 1 WR data(be sure (A[7:0] + DLen) <=256)
- uint8_t EEPROM_WrPacket(uint8_t *Buf, uint16_t DLen)
- {
- uint8_t ret;
- uint8_t AddrRWE;
- GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
- GpioSetPins(GpioPortD, GpioBitMsk10); // power on
- AddrRWE = ((Buf[0]&0x01u)<<1) | 0xA0u;
- GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
- ret = I2C1_RdWrPacket(AddrRWE, Buf+1, DLen+2);
- GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
- //us_delay(5000); // tW = 5ms
- rt_thread_mdelay(5);
- // keep I2C1_WP same level as PIN_VCC_I2C for saving power
- GpioClrPins(GpioPortD, GpioBitMsk10); // power off
- GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
- return(ret);
- }
- // size of Buf >= DLen+3 (Must)
- // Buf[0] is address A16
- // Buf[1] is address A15-A8
- // Buf[2] is address A7-A0
- // Buf[3]~Buf[DLen+2] is RD data
- // DLen>=1, at least 1 WR data
- uint8_t EEPROM_RdPacket(uint8_t *Buf, uint16_t DLen)
- {
- uint8_t ret;
- uint8_t AddrRWE;
- GpioSetPins(GpioPortA, GpioBitMsk15); // write protect on
- GpioSetPins(GpioPortD, GpioBitMsk10); // power on
- AddrRWE = ((Buf[0]&0x01u)<<1) | 0xA0u;
- ret = I2C1_RdWrPacket(AddrRWE, Buf+1, 2);
- if (ret){
- return(ret);
- }
- AddrRWE |= 0x01u;
- ret = I2C1_RdWrPacket(AddrRWE, Buf+3, DLen);
- // keep I2C1_WP same level as PIN_VCC_I2C for saving power
- GpioClrPins(GpioPortD, GpioBitMsk10); // power off
- GpioClrPins(GpioPortA, GpioBitMsk15); // write protect off
- return(ret);
- }
|