海思uboot阶段模拟i2c

理论所有linux都可以使用。在文件i2c_hibvt.c改为。下面的代码主要修改GPIO_15_BASE SCL_SHIFT_NUM,修改makefile kconfig保证代码被编译


#include <linux/errno.h>

 
#include "i2c_hibvt.h"
#define demo_delay time_delay_us(2)
#ifdef HI_FPGA
 
#define GPIO_15_BASE 0x12240000
#define SCL_SHIFT_NUM 2
#define SDA_SHIFT_NUM 3
#define SCL (0x1 << SCL_SHIFT_NUM)                                                                                   /* GPIO7 0_7 */
#define SDA (0x1 << SDA_SHIFT_NUM)                                                                                   /* GPIO7 0_6 */
#define GPIO_I2C_SCL_REG IO_ADDRESS(GPIO_15_BASE + (0x1 << (SCL_SHIFT_NUM + 2)))                                     /* 0x200 */
#define GPIO_I2C_SDA_REG IO_ADDRESS(GPIO_15_BASE + (0x1 << (SDA_SHIFT_NUM + 2)))                                     /* 0x100 */
#define GPIO_I2C_SCLSDA_REG IO_ADDRESS(GPIO_15_BASE + ((0x1 << (SCL_SHIFT_NUM + 2)) + (0x1 << (SDA_SHIFT_NUM + 2)))) /* 0x300 need check */
 
#else
/*记得修改Makefile里面的路径*/
/*下面需要修改为对应芯片的*/
#define GPIO_15_BASE 0x120b1000 
#define SCL_SHIFT_NUM 4
#define SDA_SHIFT_NUM 5
/*上面需要修改为对应芯片的*/
 
 
#define SCL (0x1 << SCL_SHIFT_NUM)                                                                                   /* GPIO1 0_7 */
#define SDA (0x1 << SDA_SHIFT_NUM)                                                                                   /* GPIO1 0_6 */
void  * GPIO_I2C_SCL_REG; 
void  * GPIO_I2C_SDA_REG;
void  * GPIO_I2C_SCLSDA_REG; /* 0x300 need check */
 
#endif
 
void  *GPIO_0_DIR; 
#define HW_REG(reg) *((volatile unsigned int *)(reg))
#define DELAY(us) time_delay_us(us)
 
/* 
 * I2C by GPIO simulated  clear 0 routine.
 *
 * @param whichline: GPIO control line
 *
 */
static void i2c_clr(unsigned char whichline)
{
    unsigned char regvalue;
 
    if (whichline == SCL)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SCL;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCL_REG) = 0;
        return;
    }
    else if (whichline == SDA)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SDA;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SDA_REG) = 0;
        return;
    }
    else if (whichline == (SDA | SCL))
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= (SDA | SCL);
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCLSDA_REG) = 0;
        return;
    }
    else
    {
        printk("Error input.\n");
        return;
    }
}
 
 
/*
 *  delays for a specified number of micro seconds rountine.
 *
 *  @param usec: number of micro seconds to pause for
 *
 */
void time_delay_us(unsigned int usec)
{
    //	volatile int i,j;
 
#ifdef HI_FPGA
    for (i = 0; i < usec * 5; i++)
    {
        for (j = 0; j < 47; j++)
        {
            ;
        }
    }
#else
    udelay(usec * 60);
 
#endif
}
/* 
 * I2C by GPIO simulated  set 1 routine.
 *
 * @param whichline: GPIO control line
 *
 */
static void i2c_set(unsigned char whichline)
{
    unsigned char regvalue;
 
    if (whichline == SCL)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SCL;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCL_REG) = SCL;
        return;
    }
    else if (whichline == SDA)
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= SDA;
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SDA_REG) = SDA;
        return;
    }
    else if (whichline == (SDA | SCL))
    {
        regvalue = HW_REG(GPIO_0_DIR);
        regvalue |= (SDA | SCL);
        HW_REG(GPIO_0_DIR) = regvalue;
 
        HW_REG(GPIO_I2C_SCLSDA_REG) = (SDA | SCL);
        return;
    }
    else
    {
        printk("Error input.\n");
        return;
    }
}
 
/* 
 * I2C by GPIO simulated  read data routine.
 *
 * @return value: a bit for read 
 *
 */
 
static unsigned char i2c_data_read(void)
{
    unsigned char regvalue;
 
    regvalue = HW_REG(GPIO_0_DIR);
    regvalue &= (~SDA);
    HW_REG(GPIO_0_DIR) = regvalue;
    DELAY(1);
 
    regvalue = HW_REG(GPIO_I2C_SDA_REG);
    if ((regvalue & SDA) != 0)
        return 1;
    else
        return 0;
}
 
static void demo_i2c_start(void)
{
    // //out_scl();
    // //out_sda();
 
    high_scl;
 
    high_sda;
    demo_delay;
    low_sda;
    demo_delay;
 
    low_scl;
}
 
static void demo_i2c_stop(void)
{
    //out_scl();
    //out_sda();
 
    high_scl;
 
    low_sda;
    demo_delay;
    high_sda;
    demo_delay;
 
    low_scl;
}
 
/*
 * sends a character over I2C rountine.
 *
 * @param  c: character to send
 *
 */
static void demo_i2c_send_byte(unsigned char data)
{
    int i = 0;
    //out_scl();
    //out_sda();
 
    low_scl;
    for(i=0;i<8;i++) {
        if(data & (0x80>>i))
            high_sda;
        else
            low_sda;
        demo_delay;
        high_scl;
        demo_delay;
        low_scl;
    }
}
 
/*  receives a character from I2C rountine.
 *
 *  @return value: character received
 *
 */
static unsigned char demo_i2c_recv_byte(void)
{
    int i = 0;
    unsigned char data = 0;
    //out_scl();
    //in_sda();
 
    low_scl;
    for(i=0;i<8;i++) {
        demo_delay;
        high_scl;
        demo_delay;
        data <<= 1;//循环8次,最终只左移了7次
        data |= i2c_data_read();
        low_scl;
    }
    return data;
}
 
 
/*  receives an acknowledge from I2C rountine.
 *
 *  @return value: 0--Ack received; 1--Nack received
 *          
 */
static unsigned char demo_i2c_recv_ack(void)
{
    int nack;
    unsigned char regvalue;
    regvalue = HW_REG(GPIO_0_DIR);
    regvalue &= (~SDA);
    HW_REG(GPIO_0_DIR) = regvalue;
 
    //DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
    i2c_set(SCL);
    DELAY(1);
 
    nack = i2c_data_read();
 
    DELAY(1);
    i2c_clr(SCL);
    DELAY(1);
 
    if (nack == 0)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}
 
 
static void demo_i2c_send_ack(unsigned char ack)
{
    //out_scl();
    //out_sda();
    low_scl;
    if(ack)
        high_sda;
    else
        low_sda;
    demo_delay;
    high_scl;
    demo_delay;
    low_scl;
}
 
 
EXPORT_SYMBOL(gpio_i2c_read);
unsigned char gpio_i2c_read(unsigned char devaddress, unsigned char address)
{
    int i = 0,len=1;
    char buff;
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress));
    if(demo_i2c_recv_ack()) {
        printk("data:0x%02x\n",(unsigned char)(devaddress));
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    demo_i2c_send_byte(address & 0xff);
    if(demo_i2c_recv_ack()) {
        printk("address:0x%02x\n",address & 0xff);
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress) | 1);
    if(demo_i2c_recv_ack()) {
        printk("devaddress:0x%02x\n",(unsigned char)(devaddress) | 1);
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
 
    for(i=0; i<(len-1); i++) {
        buff = demo_i2c_recv_byte();
        demo_i2c_send_ack(0);
    }
    buff = demo_i2c_recv_byte();
    demo_i2c_send_ack(1);
 
    demo_i2c_stop();
    return buff;
}
 
EXPORT_SYMBOL(gpio_i2c_write);
void gpio_i2c_write(unsigned char devaddress, unsigned int address, unsigned char data)
{
   int i = 0,len=1;
 
    demo_i2c_start();
    demo_i2c_send_byte((unsigned char)(devaddress));
    if(demo_i2c_recv_ack()) {
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    demo_i2c_send_byte(address & 0xff);
    if(demo_i2c_recv_ack()) {
        printf( "%d,get a nack.\n", __LINE__);
        return -1;
    }
    for(i=0; i<len; i++) {
        demo_i2c_send_byte(data);
        if(demo_i2c_recv_ack()) {
            printf( "%d,get a nack.\n", __LINE__);
            return -1;
        }
    }
 
    demo_i2c_stop();
    return i;
}
 
#if 0
long gpioi2c_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret;
    unsigned char device_addr;
    unsigned int reg_addr;
    unsigned int reg_val;
    GPIOI2C_DATA_S i2c_data_t;
 
    switch (cmd)
    {
    case GPIO_I2C_READ:
         ret=copy_from_user(&i2c_data_t, (GPIOI2C_DATA_S *)arg, sizeof(GPIOI2C_DATA_S));
        device_addr = i2c_data_t.dev_addr;
        reg_addr = i2c_data_t.reg_addr;
        i2c_data_t.data = gpio_i2c_read(device_addr, reg_addr);
        printk("GPIO_I2C_READ--device_addr:0x%02x  reg_addr:0x%02x  reg_val:0x%02x\n", device_addr, reg_addr,  i2c_data_t.data);
        ret=copy_to_user((GPIOI2C_DATA_S *)arg, &i2c_data_t, sizeof(GPIOI2C_DATA_S));
        break;
 
    case GPIO_I2C_SELCHN:
 
        break;
 
    case GPIO_I2C_WRITE:
        ret=copy_from_user(&i2c_data_t, (GPIOI2C_DATA_S *)arg, sizeof(GPIOI2C_DATA_S));
        device_addr = i2c_data_t.dev_addr;
        reg_addr = i2c_data_t.reg_addr;
        reg_val = i2c_data_t.data;
        gpio_i2c_write(device_addr, reg_addr, reg_val);
        break;
    case GPIO_I2C_WRITE2:
        ret=copy_from_user(&i2c_data_t, (GPIOI2C_DATA_S *)arg, sizeof(GPIOI2C_DATA_S));
        break;
    case GPIO_I2C_WRITE4:
        ret=copy_from_user(&i2c_data_t, (GPIOI2C_DATA_S *)arg, sizeof(GPIOI2C_DATA_S));
        break;
 
    default:
        printk("error!!%d\n", cmd);
        return -1;
    }
    return 0;
}
#endif
int gpioi2c_open(struct inode *inode, struct file *file)
{
    return 0;
}
int gpioi2c_close(struct inode *inode, struct file *file)
{
    return 0;
}
 

 
int  gpio_i2c_init(void)
{
    int ret;
    //unsigned int reg;
    GPIO_0_DIR=ioremap(GPIO_15_BASE + 0x400, 1); /* GPIO direction reg */
    GPIO_I2C_SCL_REG=ioremap(GPIO_15_BASE + (0x1 << (SCL_SHIFT_NUM + 2)), 1);                                     /* 0x200 */
    GPIO_I2C_SDA_REG=ioremap(GPIO_15_BASE + (0x1 << (SDA_SHIFT_NUM + 2)), 1);      
    GPIO_I2C_SCLSDA_REG=ioremap(GPIO_15_BASE + ((0x1 << (SCL_SHIFT_NUM + 2)) + (0x1 << (SDA_SHIFT_NUM + 2))), 1); 

    return 0;
}
 
void gpio_i2c_exit(void)
{
    iounmap(GPIO_0_DIR); /* GPIO direction reg */
    iounmap(GPIO_I2C_SCL_REG);                                     /* 0x200 */
    iounmap(GPIO_I2C_SDA_REG);      
    iounmap(GPIO_I2C_SCLSDA_REG); 
}
 
 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要使用海思i2c工具来读写imx334 id,我们可以按照以下步骤进行操作: 1. 连接硬件:将imx334摄像头模块与处理器的i2c总线相连。确保电源供应正常并且连接正确。 2. 安装海思i2c工具:在处理器上安装海思i2c工具软件包,包括i2cdetect和i2cget。这些工具将帮助我们进行i2c设备的探测和读写操作。 3. 找到imx334摄像头的i2c地址:使用i2cdetect工具来扫描i2c总线,并查找imx334摄像头的i2c地址。运行i2cdetect -y -r 0命令,其中“0”是i2c总线编号,根据具体配置进行调整。命令的输出将显示i2c总线上找到的设备地址。找到imx334摄像头的i2c地址后,我们可以使用这个地址进行后续的读写操作。 4. 读取imx334 id:使用i2cget工具,运行i2cget -y -r 0 i2c_address register_address命令来读取imx334摄像头的id。其中,“i2c_address”是我们在前一步中找到的imx334摄像头的i2c地址,“register_address”是imx334摄像头的注册地址。运行命令后,将会打印出imx334的id。 5. 写入imx334 id:使用i2cset工具,运行i2cset -y -r 0 i2c_address register_address value命令来写入imx334摄像头的id。其中,“i2c_address”是我们在前一步中找到的imx334摄像头的i2c地址,“register_address”是imx334摄像头的注册地址,“value”是需要写入的id值。运行命令后,将会将id写入imx334摄像头。 通过以上的步骤,我们可以使用海思i2c工具来读写imx334摄像头的id信息。 ### 回答2: 要使用海思 i2c tools读写imx334 id,需要执行以下步骤: 1. 确保你的系统上已经安装了海思i2c tools软件包。你可以通过在终端中运行以下命令来检查是否安装了这个软件包: ``` i2cdetect -l ``` 如果运行结果中显示有海思i2c设备列表,则说明软件包已经正确安装。 2. 确定imx334相机模组的i2c地址。使用以下命令可以扫描系统上连接的i2c设备,并显示每个设备的地址: ``` i2cdetect -y <i2c-bus号> ``` 在运行命令时,将<i2c-bus号>替换为相机模组所连接的i2c总线号。例如,如果相机连接到i2c-1总线上,则命令应为: ``` i2cdetect -y 1 ``` 运行命令后,你将看到一个i2c设备网格,显示了每个设备的地址。寻找imx334模组对应的地址。 3. 读取imx334的id。使用以下命令可以读取imx334模组的id: ``` i2cget -y <i2c-bus号> <i2c地址> <寄存器地址> [w] ``` 在运行命令时,将<i2c-bus号>替换为相机模组所连接的i2c总线号,<i2c地址>替换为imx334模组的i2c地址,<寄存器地址>替换为id寄存器的地址。如果id是16位的,可以在命令的末尾添加[w]选项以读取完整的16位id值。 例如,如果imx334模组的i2c地址为0x30,id寄存器地址为0x00,则命令应为: ``` i2cget -y 1 0x30 0x00 w ``` 运行命令后,将显示imx334模组的id值。 通过执行上述步骤,你可以使用海思i2c tools读取imx334模组的id。注意,确保在操作i2c设备时具备足够的权限,并正确连接imx334模组到i2c总线上。 ### 回答3: IMX334是一种高性能的CMOS图像传感器,常用于工业相机和监控设备中。要使用海思(HiSilicon)公司的I2C工具来读写IMX334的ID,可以按照以下步骤进行。 首先,需要将IMX334连接到主控制器上,通常会使用一些引脚将两者连接起来。确保连接正确并且稳定。 接下来,使用I2C工具在主控制器上打开I2C总线。I2C总线是一种串行通信协议,用于在电子设备之间传输数据。通过I2C总线,主控制器可以与IMX334进行通信。 在I2C工具中,您需要设置正确的I2C地址。每个I2C设备都有一个独特的地址,用于在总线上进行识别。查阅IMX334的数据手册,找到正确的I2C地址并设置到工具中。 一旦I2C地址设置完毕,您可以使用I2C工具发送读取指令来读取IMX334的ID。指令的格式和具体内容会根据I2C工具的不同而有所差异。根据IMX334的数据手册,找到对应的读取ID的指令,并将其发送到IMX334。 IMX334会响应读取指令,并返回其ID。您可以通过I2C工具接收并显示ID。 要写入IMX334的ID,可以使用相似的步骤。首先设置I2C地址到I2C工具中,然后发送写入指令和具体的ID值。 请注意,上述步骤只是一个大致的指导,具体的步骤可能因为使用的工具和设备而有所差异。对于准确的操作指导,请参考IMX334和所使用I2C工具的详细文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值