需要在uboot中检测i2c值作为脚本

时间:2017-08-06 15:43:32

标签: i2c u-boot

我希望在uboot中读取i2c的值, 并根据值,执行命令。我需要它在脚本中

命令本身并不重要,但是,它的激活必须基于i2c芯片的值。

到目前为止,我只能打印i2c中的值,但我无法使用它们。

=> i2c md 20.1 0 8
0000: ff ff ff ff ff ff ff ff    ........

我也有条件:

=> setenv myvalue 0
=> if test $myvalue -eq 1; then echo 'hello'; fi
=> setenv myvalue 1
=> if test $myvalue -eq 1; then echo 'hello'; fi
hello
=>

我可以针对i2c做一些特定的事情:

=> if i2c probe; then echo "true"; else echo "false"; fi
Valid chip addresses: 20 21 22 23
true

但我无法将i2c中的值用于条件。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

我没有看到任何直截了当的方法,但以下情况应该有效:

  1. 使用i2c read
  2. 将I2C数据读入内存
  3. 使用mw将比较值写入内存中。
  4. 使用cmp比较两个内存区域 - 这应该以{{1​​}}的形式工作,以根据结果有条件地执行某些操作。
  5. 您将不知何故必须知道特定系统上的RAM块的地址,这些RAM可以在引导过程的这个阶段安全地写入。

答案 1 :(得分:0)

u-boot中没有提供解决方案来实现您的目标(轻松)。我编写了一个u-boot命令,它允许您从RAM读取并将值存储到一个环境变量中,以便您进行比较。

#include <common.h>
#include <config.h>
#include <command.h>

int do_setenvram(
    cmd_tbl_t *cmdtp,
    int flag,
    int argc,
    char *argv[]
) {

    unsigned int *addr;
    unsigned long len;
    uint32_t val;
    char buffer[200];
    char type;
    char returntype;

    if ( argc < 3 || argc > 4 )  {
        printf ("Usage:\n%s\n", cmdtp->usage);
        return 1;
    }

    addr = (char *)simple_strtol(argv[2], NULL, 16);

    if ( !addr ) {
        printf ("Usage:\n%s\n", cmdtp->usage);
        return 1;
    }

    if ( argc == 4 ) {
        len = simple_strtol(argv[3], NULL, 16);
        if ( !len || len >= buffer ) {
            printf ("Usage:\n%s\n", cmdtp->usage);
            return 1;
        }
    }

    int option = strlen(argv[0]);

    if ( option > 2 && argv[0][option-3] == '.' ) {
        type = argv[0][option-2];
        returntype = argv[0][option-1];
    } else if ( option > 2 && argv[0][option-2] == '.' ) {
        type = argv[0][option-1];
    } else {
        printf ("Usage:\n%s\n", cmdtp->usage);
        return 1;
    }

    switch ( type ) {
        case 'b':
            val = *((unsigned char *)(addr));
            break;
        case 'w':
            addr = (unsigned short *)simple_strtol(argv[2], NULL, 16);
            val = ntohs(*addr);
            break;
        case 'l':
            addr = (unsigned int *)simple_strtol(argv[2], NULL, 16);
            val = htonl(*addr);
            break;
        case 'k':
            addr = (unsigned int *)simple_strtol(argv[2], NULL, 16);
            val = (*addr);
            break;
        case 's':
            memset(buffer, 0, sizeof(buffer));
            memcpy(buffer, addr, len);
            break;
        default:
            return 0;
    }

    if ( returntype == 'd' ) {
        sprintf(buffer, "%d", val);
    } else if ( type != 's' ) {
        sprintf(buffer, "0x%x", val);
    }

    setenv(argv[1], buffer);
    return 0;
}

/* ------------------------------------------------------------------------- */

U_BOOT_CMD(
    setenvram, 4, 0, do_setenvram,
    "set environment variable from ram",
    "name addr {len}\n"
    "[.b, .w, .l, .s, .k] name address {max_length}\n"
    "    - set environment variable 'name' from addr 'addr'\n"
);

所以在你的情况下:

  1. 从i2c读取到内存中的位置(可以免费或可以写入):i2c read <chip> <memory-location>
  2. 确认它已写入提供的内存位置:md <memory-location>
  3. 您需要知道从内存中读取的预期数据,从长度的角度来看,以及它是大端还是小端。
  4. 您可以通过setenvram.x <variable-name> <memory-location> <length>使用我在上面提供的u-boot命令,其中参数.x是以下之一:
  5.   

    参数[1]选项:

         

    .b - 位(1个字节)。

         

    .w - 字(2个字节)。主机 - 网络字节转换。

         

    .l - 长(4个字节)。主机 - 网络字节转换。

         

    .k - 长(4个字节)。

         

    .s - string(用户指定的字节数)。 //注意:{length}是必需的。

    1. 从这里开始,存储在内存中的值现在将位于u-boot环境变量中,可用于比较。
    2. 在此处的提交中可以看到更多示例和用法:https://github.com/bwenstar/uboot-imx/commit/5996e854f82ecb9005d2b9546a71fca458784204