Linux 如何在MIPS板的u引导代码中增加对位碰撞i2c总线的支持
我有一个MIPS板AR9341,我想在其中添加对从u引导本身而不是从内核启动i2c总线的支持 我还有两个免费的GPIO,可用于SDA和SCL Pin 我还阅读了一些文档和用户指南,关于如何在u引导中添加支持位的i2c总线,但没有得到正确的想法 关于如何从u引导使用GPIOs添加对位碰撞i2c总线的支持,有人有任何文档或想法吗 如果有人对此有想法,请尽快帮助我 我曾尝试从u boot用两个LED设置并清除两个GPIO,它工作正常,没有任何问题。现在我想将这两个GPIO连接为SDA和SCL行,用于软件位碰撞Linux 如何在MIPS板的u引导代码中增加对位碰撞i2c总线的支持,linux,mips,i2c,u-boot,Linux,Mips,I2c,U Boot,我有一个MIPS板AR9341,我想在其中添加对从u引导本身而不是从内核启动i2c总线的支持 我还有两个免费的GPIO,可用于SDA和SCL Pin 我还阅读了一些文档和用户指南,关于如何在u引导中添加支持位的i2c总线,但没有得到正确的想法 关于如何从u引导使用GPIOs添加对位碰撞i2c总线的支持,有人有任何文档或想法吗 如果有人对此有想法,请尽快帮助我 我曾尝试从u boot用两个LED设置并清除两个GPIO,它工作正常,没有任何问题。现在我想将这两个GPIO连接为SDA和SCL行,用于软
有人知道如何在u引导代码本身中将GPIOs配置为SDA和SCL行吗?您可以尝试获得一个位碰撞I²C主协议的示例,并将其移植到MCU硬件上 下面是一个将I²C协议作为I²C主机进行位碰撞的示例。该示例是用伪C编写的。它说明了前面描述的所有I²C功能(时钟拉伸、仲裁、开始/停止位、ack/nack)
//I2C的端口
#定义I2C_DDR DDRD
#定义I2C_引脚PIND
#定义I2C_端口端口D
//钻头冲击中使用的销
#定义I2C_CLK 0
#定义I2C_数据1
#定义I2C_数据_HI()\
I2C_DDR&=~(1@Rulsan感谢您的回复。如何在u-boot本身的我的板文件中添加SDA和SCL引脚的GPIO配置?您对此有什么想法吗?对于软件i2c位碰撞,它应该是基于ioport或基于io内存的配置?我对uboot知之甚少,但您以前对任何GPIO线都有简单的访问和控制吗s、 在选定行上设置1
或0
这样的简单操作之前,您能做吗?实现这一点,您至少应该确保它是您的API(它只是C或ASM中的一个代码字符串)简单工作-您可以通过万用表测量该引脚上的电压或通过示波器观察线路来进行检查。实现并自然检查这组简单的线路控制功能后,您可以依赖上面的伪C代码。此外,您最有可能实现I/O方向开关。我目前正在将1或0设置为two从u-boot代码本身释放GPIO。然后,我将尝试使用SDA和SCL线这两个GPIO添加软件位碰撞支持。我尝试从u-boot代码本身控制GPIO,它工作正常,没有任何问题。我不知道如何在u-boot级别添加软件i2c支持。您知道使用ioport或iomemory吗o在u-boot级别添加对i2c位碰撞的支持?很好,现在包括提供的所有代码并尝试编译,解决所有编译问题(如果有),并实现特定于硬件的功能,如bool read_SCL(void);bool read_SDA(void);void clear_SCL(void);void clear_SDA(void);
// Hardware-specific support functions that MUST be customized:
#define I2CSPEED 100
void I2C_delay() { volatile int v; int i; for (i=0; i < I2CSPEED/2; i++) v; }
bool read_SCL(void); // Set SCL as input and return current level of line, 0 or 1
bool read_SDA(void); // Set SDA as input and return current level of line, 0 or 1
void clear_SCL(void); // Actively drive SCL signal low
void clear_SDA(void); // Actively drive SDA signal low
void arbitration_lost(void);
bool started = false; // global data
void i2c_start_cond(void) {
if (started) { // if started, do a restart cond
// set SDA to 1
read_SDA();
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// Repeated start setup time, minimum 4.7us
I2C_delay();
}
if (read_SDA() == 0) {
arbitration_lost();
}
// SCL is high, set SDA from 1 to 0.
clear_SDA();
I2C_delay();
clear_SCL();
started = true;
}
void i2c_stop_cond(void){
// set SDA to 0
clear_SDA();
I2C_delay();
// Clock stretching
while (read_SCL() == 0) {
// add timeout to this loop.
}
// Stop bit setup time, minimum 4us
I2C_delay();
// SCL is high, set SDA from 0 to 1
if (read_SDA() == 0) {
arbitration_lost();
}
I2C_delay();
started = false;
}
// Write a bit to I2C bus
void i2c_write_bit(bool bit) {
if (bit) {
read_SDA();
} else {
clear_SDA();
}
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
// If SDA is high, check that nobody else is driving SDA
if (bit && read_SDA() == 0) {
arbitration_lost();
}
I2C_delay();
clear_SCL();
}
// Read a bit from I2C bus
bool i2c_read_bit(void) {
bool bit;
// Let the slave drive data
read_SDA();
I2C_delay();
while (read_SCL() == 0) { // Clock stretching
// You should add timeout to this loop
}
// SCL is high, now data is valid
bit = read_SDA();
I2C_delay();
clear_SCL();
return bit;
}
// Write a byte to I2C bus. Return 0 if ack by the slave.
bool i2c_write_byte(bool send_start,
bool send_stop,
unsigned char byte) {
unsigned bit;
bool nack;
if (send_start) {
i2c_start_cond();
}
for (bit = 0; bit < 8; bit++) {
i2c_write_bit((byte & 0x80) != 0);
byte <<= 1;
}
nack = i2c_read_bit();
if (send_stop) {
i2c_stop_cond();
}
return nack;
}
// Read a byte from I2C bus
unsigned char i2c_read_byte(bool nack, bool send_stop) {
unsigned char byte = 0;
unsigned bit;
for (bit = 0; bit < 8; bit++) {
byte = (byte << 1) | i2c_read_bit();
}
i2c_write_bit(nack);
if (send_stop) {
i2c_stop_cond();
}
return byte;
}
#include "pic16lf1947.h"
#include "PIC16_I2C_BITBANG.h"
#include "xc.h"
//....................................................................
// This function generates an I2C Start Condition
//....................................................................
void i2c_start(void)
{
unsigned int i;
SDA_TRIS = 1; // ensure SDA & SCL are high
SCL = 1;
SDA_TRIS = 0; // SDA = output
SDA = 0; // pull SDA low
for (i=0;i<2;i++) NOP();
SCL = 0; // pull SCL low
}
//....................................................................
// This function generates an I2C Stop Condition
//....................................................................
void i2c_stop(void)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS = 0; // SDA = output
SDA = 0; // SDA low
for (i=0;i<3;i++) NOP();
SCL = 1; // pull SCL high
SDA_TRIS = 1; // allow SDA to be pulled high
for (i=0;i<3;i++) NOP();
SCL=0; // ensure SCL is low
}
//.......................................................... AR9341..........
// Outputs a bit to the I2C bus
//....................................................................
void bit_out(unsigned char data)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS=0; // configure SDA as an output
SDA= (data>>7); // output the MSB
for (i=0;i<2;i++) NOP();
SCL = 1; // pull SCL high to clock bit
for (i=0;i<3;i++) NOP();
SCL = 0; // pull SCL low for next bit
}
//....................................................................
// Inputs a bit from the I2C bus
//....................................................................
void bit_in(unsigned char *data)
{
unsigned int i;
SCL = 0; // ensure SCL is low
SDA_TRIS = 1; // configure SDA as an input
SCL = 1; // bring SCL high to begin transfer
for (i=0;i<3;i++) NOP();
*data |= SDA; // input the received bit
SCL = 0; // bring SCL low again.
}
//....................................................................
// Writes a byte to the I2C bus
//....................................................................
unsigned char i2c_wr(unsigned char data)
{
unsigned char i; // loop counter
unsigned char ack; // ACK bit
ack = 0;
for (i = 0; i < 8; i++) // loop through each bit
{
bit_out(data); // output bit
data = data << 1; // shift left for next bit
}
bit_in(&ack); // input ACK bit
return ack;
}
//....................................................................
// Reads a byte from the I2C bus
//....................................................................
unsigned char i2c_rd(unsigned char ack)
{
unsigned char i; // loop counter
unsigned char ret=0; // return value
for (i = 0; i < 8; i++) // loop through each bit
{
ret = ret << 1; // shift left for next bit
bit_in(&ret); // input bit
}
bit_out(ack); // output ACK/NAK bit
return ret;
}
//.............................................................................
// Polls the bus for ACK from device
//.............................................................................
void ack_poll (unsigned char control)
{
unsigned char result=1;
while(result)
{
i2c_start(); // generate Restart condition
result=i2c_wr(control); // send control byte (WRITE command)
}
i2c_stop(); // generate Stop condition
}
// Port for the I2C
#define I2C_DDR DDRD
#define I2C_PIN PIND
#define I2C_PORT PORTD
// Pins to be used in the bit banging
#define I2C_CLK 0
#define I2C_DAT 1
#define I2C_DATA_HI()\
I2C_DDR &= ~ (1 << I2C_DAT);\
I2C_PORT |= (1 << I2C_DAT);
#define I2C_DATA_LO()\
I2C_DDR |= (1 << I2C_DAT);\
I2C_PORT &= ~ (1 << I2C_DAT);
#define I2C_CLOCK_HI()\
I2C_DDR &= ~ (1 << I2C_CLK);\
I2C_PORT |= (1 << I2C_CLK);
#define I2C_CLOCK_LO()\
I2C_DDR |= (1 << I2C_CLK);\
I2C_PORT &= ~ (1 << I2C_CLK);
void I2C_WriteBit(unsigned char c)
{
if (c > 0)
{
I2C_DATA_HI();
}
else
{
I2C_DATA_LO();
}
I2C_CLOCK_HI();
delay(1);
I2C_CLOCK_LO();
delay(1);
if (c > 0)
{
I2C_DATA_LO();
}
delay(1);
}
unsigned char I2C_ReadBit()
{
I2C_DATA_HI();
I2C_CLOCK_HI();
delay(1);
unsigned char c = I2C_PIN;
I2C_CLOCK_LO();
delay(1);
return (c >> I2C_DAT) & 1;
}
// Inits bitbanging port, must be called before using the functions below
//
void I2C_Init()
{
I2C_PORT &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
I2C_CLOCK_HI();
I2C_DATA_HI();
delay(1);
}
// Send a START Condition
//
void I2C_Start()
{
// set both to high at the same time
I2C_DDR &= ~ ((1 << I2C_DAT) | (1 << I2C_CLK));
delay(1);
I2C_DATA_LO();
delay(1);
I2C_CLOCK_LO();
delay(1);
}
// Send a STOP Condition
//
void I2C_Stop()
{
I2C_CLOCK_HI();
delay(1);
I2C_DATA_HI();
delay(1);
}
// write a byte to the I2C slave device
//
unsigned char I2C_Write(unsigned char c)
{
for (char i = 0; i < 8; i++)
{
I2C_WriteBit(c & 128);
c <<= 1;
}
//return I2C_ReadBit();
return 0;
}
// read a byte from the I2C slave device
//
unsigned char I2C_Read(unsigned char ack)
{
unsigned char res = 0;
for (char i = 0; i < 8; i++)
{
res <<= 1;
res |= I2C_ReadBit();
}
if (ack > 0)
{
I2C_WriteBit(0);
}
else
{
I2C_WriteBit(1);
}
delay(1);
return res;
}