c - 从用户区读取 32k i2c eeprom

标签 c linux dump i2c eeprom

我需要读取嵌入式设备中的 eeprom。

到目前为止,这个“几乎”有效:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>

#include <linux/i2c-dev.h>


#define READ_SIZE   (256)
#define NB_PAGES    (128)



void dump_to_file(const char *output_file_path,
          const uint8_t *buffer, const int buffer_length)
{
    int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
    if (output_file < 0) {
        printf("Failed opening output file %s\n", output_file_path);
        return;
    }

    write(output_file, buffer, buffer_length);
}


int main(int argc, char *argv[])
{
    /* got these values from i2cdetect */
    const char *i2c_device = "/dev/i2c-4";
    const int device_address = 0x50;

    /* open the i2c device file */
    int file = open(i2c_device, O_RDWR);
    if (file < 0) {
        printf("Failed opening %s\n", i2c_device);
        return 1;
    }

    if (ioctl(file, I2C_SLAVE, device_address) < 0) {
        printf("Failed addressing device at %02X\n", device_address);
        close(file);
        return 1;
    }

    int i = 0;
    for (i = 0; i < NB_PAGES; i++) {
        char buf[READ_SIZE] = {0};

        if (read(file, buf, READ_SIZE) != READ_SIZE) {
            printf("Failed reading\n");
            close(file);
            return 1;
        }

        dump_to_file(argv[1], buf, READ_SIZE);
    }

    close(file);

    return 0;
}

“几乎”是指它转储完整的 eeprom,但 START 取决于最后读取的 block 。
它并不总是一样的。
如果我读了 10 个 block 。然后再次运行该程序,我读了接下来的内容,而不是前 10 个。

如何设置起始地址?

更新: 如果我这样做:

i2cset -y 4 0x50 0x00 0x00

并运行上面的代码,它可以工作。 那么如何在代码中放入 i2cset 命令的等效命令呢?

最佳答案

完成! 这并不容易,因为我在任何地方都找不到文档..但我认为由于 eeprom 是 32K,也许它“就像”24c256。但即使在这种情况下,我在用户空间中也找不到任何东西,直到我决定凭直觉去做。 我研究了 i2cset 源代码,了解了它的作用并将其放入代码中。

这是结果,它从用户空间转储完整的 i2c 32k eprom。

请注意,可以在此处找到完整的备份和恢复实用程序: https://gist.github.com/Zibri/cf8ac0b311301aeeaa8910c7da824bff

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>


#define READ_SIZE       (256)
#define NB_PAGES        (128)

void dump_to_file(const char *output_file_path,
                  const uint8_t *buffer, const int buffer_length)
{
        int output_file = open(output_file_path, O_RDWR|O_APPEND|O_CREAT);
        if (output_file < 0) {
                printf("Failed opening output file %s\n", output_file_path);
                return;
        }

        write(output_file, buffer, buffer_length);
}


int main(int argc, char *argv[])
{

        const char *i2c_device = "/dev/i2c-4";
        const int device_address = 0x50;

        int file = open(i2c_device, O_RDWR);
        if (file < 0) {
                printf("Failed opening %s\n", i2c_device);
                return 1;
        }

        if (ioctl(file, I2C_SLAVE, device_address) < 0) {
                printf("Failed addressing device at %02X\n", device_address);
                close(file);
                return 1;
        }

        int i = 0;

        write(file,'\x00\x00',2); // ADDRESS

        for (i = 0; i < NB_PAGES; i++) {
                char buf[READ_SIZE] = {0};

                if (read(file, buf, READ_SIZE) != READ_SIZE) {
                        printf("Failed reading\n");
                        close(file);
                        return 1;
                }

                dump_to_file(argv[1], buf, READ_SIZE);
        }

        close(file);

        return 0;
}

关于c - 从用户区读取 32k i2c eeprom,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68878486/

相关文章:

c - C中struct的双指针是什么意思

c - 在 sprintf 中隐藏整数

c - 如何在内存中保留一个非常大的数据集的多个副本?

c++ - 堆上的类内的 Linux fork

mysql - 从 "data"文件夹mysql转储数据

c - 如何在c中操作整数类型的位?

linux - Linux 上的 ASP.NET Core Windows 身份验证

linux - 通过中间机器挂载远程文件系统(sshfs)

postgresql 数据库结构脚本

macos - 如何创建 Mac OS 应用程序的内存转储