pdk7105的I2C配置
stm23-0047版本中增加了I2C的配置
<<include/configs/pdk7105.h>>
已知:
PIO3[4] SCL
PIO3[5] SDA
根据board/st/pdk7105.c代码中
static void configI2c(void)
{
/*
* The I2C busses are routed as follows:
*
* Bus SCL SDA
* --- --- ---
* A PIO2[2] PIO2[3]
* B PIO2[5] PIO2[6] Used only for SPI
* C PIO3[4] PIO3[5]
* D PIO3[6] PIO3[7]
*/
#if defined(CONFIG_I2C_BUS_A) /* Use I2C Bus "A" */
SET_PIO_PIN(PIO_PORT(2),2,STPIO_BIDIR); /* I2C_SCLA */
SET_PIO_PIN(PIO_PORT(2),3,STPIO_BIDIR); /* I2C_SDAA */
#elif defined(CONFIG_I2C_BUS_C) /* Use I2C Bus "C" */
SET_PIO_PIN(PIO_PORT(3),4,STPIO_BIDIR); /* I2C_SCLC */
SET_PIO_PIN(PIO_PORT(3),5,STPIO_BIDIR); /* I2C_SDAC */
#elif defined(CONFIG_I2C_BUS_D) /* Use I2C Bus "D" */
SET_PIO_PIN(PIO_PORT(3),6,STPIO_BIDIR); /* I2C_SCLD */
SET_PIO_PIN(PIO_PORT(3),7,STPIO_BIDIR); /* I2C_SDAD */
#else
#error Unknown I2C Bus!
#endif
}
选用C总线,故定义CONFIG_I2C_BUS_C
SET_PIO_PIN(PIO_PORT(3),4,STPIO_BIDIR); /* I2C_SCLC */
SET_PIO_PIN(PIO_PORT(3),5,STPIO_BIDIR); /* I2C_SDAC */
#define SET_PIO_PIN(PIO_ADDR, PIN, DIR) /
do { /
writel( PIN_C0((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC0_OFFSET+STPIO_SET_OFFSET); /
writel( PIN_C1((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC1_OFFSET+STPIO_SET_OFFSET); /
writel( PIN_C2((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC2_OFFSET+STPIO_SET_OFFSET); /
writel( CLEAR_PIN_C0((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC0_OFFSET+STPIO_CLEAR_OFFSET); /
writel( CLEAR_PIN_C1((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC1_OFFSET+STPIO_CLEAR_OFFSET); /
writel( CLEAR_PIN_C2((PIN),(DIR)), /
(PIO_ADDR)+STPIO_PC2_OFFSET+STPIO_CLEAR_OFFSET); /
} while (0)
#define PIN_C0(PIN, DIR) PIN_CX((PIN), (DIR), 0x01)
#define PIN_C1(PIN, DIR) PIN_CX((PIN), (DIR), 0x02)
#define PIN_C2(PIN, DIR) PIN_CX((PIN), (DIR), 0x04)
#define PIN_CX(PIN, DIR, X) (((PIN)==STPIO_NO_PIN) ? 0 : (((DIR) & (X))!=0) << (PIN))//将PIN口的位0,1,2置1
#define writel(b,addr) ((*(volatile u32 *) (addr)) = (b))//将b写入地址addr(long:32位)
SET_PIO_PIN(PIO_PORT(3),4,STPIO_BIDIR); /* I2C_SCLC */将ST40_PIO3_REGS_BASE(0xfd023000)的第4位置1
SET_PIO_PIN(PIO_PORT(3),5,STPIO_BIDIR); /* I2C_SDAC */将ST40_PIO3_REGS_BASE(0xfd023000)的第5位置1
SET_PIO_PIN(PIO_PORT(3),4,STPIO_BIDIR);//等价于*(0xfd023000)|=(1<<4)
extern void stx7105_i2c_scl(const int val)
{
#if defined(CONFIG_I2C_BUS_A) /* Use I2C Bus "A" */
STPIO_SET_PIN(PIO_PORT(2), 2, (val) ? 1 : 0);
#elif defined(CONFIG_I2C_BUS_C) /* Use I2C Bus "C" */
STPIO_SET_PIN(PIO_PORT(3), 4, (val) ? 1 : 0);
#elif defined(CONFIG_I2C_BUS_D) /* Use I2C Bus "D" */
STPIO_SET_PIN(PIO_PORT(3), 6, (val) ? 1 : 0);
#endif
}
stx7105_i2c_scl(const int val)设置PIO3[4]的值为val[0:1]
extern void stx7105_i2c_sda(const int val)
{
#if defined(CONFIG_I2C_BUS_A) /* Use I2C Bus "A" */
STPIO_SET_PIN(PIO_PORT(2), 3, (val) ? 1 : 0);
#elif defined(CONFIG_I2C_BUS_C) /* Use I2C Bus "C" */
STPIO_SET_PIN(PIO_PORT(3), 5, (val) ? 1 : 0);
#elif defined(CONFIG_I2C_BUS_D) /* Use I2C Bus "D" */
STPIO_SET_PIN(PIO_PORT(3), 7, (val) ? 1 : 0);
#endif
}
stx7105_i2c_sda(const int val)设置PIO3[5]值为val
extern int stx7105_i2c_read(void)
{
#if defined(CONFIG_I2C_BUS_A) /* Use I2C Bus "A" */
return STPIO_GET_PIN(PIO_PORT(2), 3);
#elif defined(CONFIG_I2C_BUS_C) /* Use I2C Bus "C" */
return STPIO_GET_PIN(PIO_PORT(3), 5);
#elif defined(CONFIG_I2C_BUS_D) /* Use I2C Bus "D" */
return STPIO_GET_PIN(PIO_PORT(3), 7);
#endif
}
stx7105_i2c_read(void)获取PIO3[5]的值STPIO_GET_PIN(PIO_PORT(3),5)
/*----------------------------------------------------------------------
* I2C configuration
*/
#define CONFIG_CMD_I2C /* do we want I2C support ? */
#if defined(CONFIG_CMD_I2C)
# define CONFIG_I2C_BUS_C /* Use I2C Bus "C" */
# define CONFIG_I2C_CMD_TREE /* use a "i2c" root command */
# define CFG_I2C_SLAVE 0x7F /* I2C slave address */ /* QQQ - TO CHECK */
# define CONFIG_SOFT_I2C /* I2C with S/W bit-banging */
# undef CONFIG_HARD_I2C /* I2C withOUT hardware support */
# define I2C_ACTIVE /* open-drain, nothing to do */
# define I2C_TRISTATE /* open-drain, nothing to do */
# define I2C_SCL(val) do { stx7105_i2c_scl((val)); } while (0)
# define I2C_SDA(val) do { stx7105_i2c_sda((val)); } while (0)
# define I2C_READ stx7105_i2c_read()
/*
* The "BOGOS" for NDELAY() may be calibrated using the
* following code fragment, and measuring (using an oscilloscope)
* the frequency of the I2C SCL pin, and adjusting
* NDELAY_BOGOS, until the SCL is approximately 100 kHz.
* (100kHz has a period of 5us + 5us).
*
* printf("just toggling I2C SCL (100kHz frequency) .../n");
* while (1)
* {
* I2C_SCL(1); NDELAY(5000);
* I2C_SCL(0); NDELAY(5000);
* }
*/
# define NDELAY_BOGOS 22 /* Empirical measurement for 1ns */
# define NDELAY(ns) /
do { /
const unsigned n_bogo = NDELAY_BOGOS; /
const unsigned n_ticks = /
((ns)<n_bogo) ? 1u : (ns)/n_bogo; /
volatile unsigned n_count; /
for(n_count=0; n_count<n_ticks; n_count++) /
; /* do nothing */ /
} while(0)
/*
* Note there are 4 * I2C_DELAY per I2C clock cycle
* So, 400 kHz requires an I2C delay of 625 ns.
* However, this calculation only works if the S/W
* overhead in I2C bit-banging is negligible - which it is not!
* So, in practice, either I2C_DELAY or CFG_I2C_SPEED will be lower.
* The higher the clock frequency, the greater the difference.
* Empirical measurement/adjustment is recommended.
*/
# define CFG_I2C_SPEED 400000 /* I2C speed (Hz) */
# define I2C_DELAY do { NDELAY(625); } while (0) /* 625 ns */
#endif /* CONFIG_CMD_I2C */
#endif /* __CONFIG_H */
I2C_SCL(1) SCL置高
I2C_SDA(val) SDA
NDELAY(ns)
# define I2C_READ stx7105_i2c_read() STPIO_GET_PIN(PIO_PORT(3), 5);
I2C总线在传送数据过程中共有三种类型信号, 它们分别是:开始信号、结束信号和应答信号。
开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲,表示已收到数据。
CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。
若未收到应答信号,由判断为受控单元出现故障。