Acessando o GPIO depois que o kernel inicializar

1

meu rootfs.cpio tem apenas os seguintes arquivos:

[root@localhost extract]# ls 
dev  init  tmp

dev tem apenas console.

O

init é compilado pelo programa no final:

Então eu faço uma imagem minha e executo o linux. Ele roda bem, mas quando o init chega, ele mostra um erro semelhante ao seguinte:

Failed to open /sys/class/gpio/gpio251/direction  
Failed to open /sys/class/gpio/gpio251/value

Então, eu criei manualmente essas pastas e arquivos e agora é assim:

[root@localhost extract]# ls 
    dev  init  tmp sys

dentro do sys eu criei pastas e arquivos necessários (vazios).

Mas mesmo assim o código não está sendo executado e o kernel entra em pane.

Plano de fundo

Esse código eu peguei de um sistema de arquivos completo, que tinha todos os diretórios esperados em um sistema Linux. Eu peguei este código compilado separadamente e renomei para init.

E esperando trabalhar (Luz, um LED, por exemplo).

Outra abordagem

bash> echo 240 > /sys/class/gpio/export
bash> echo out > /sys/class/gpio/gpio240/direction
bash> echo 1 > /sys/class/gpio/gpio240/value

Essa abordagem é descrita GPIO DRIVER . Então, depois de criar manualmente esses arquivos necessários, eu os compilei e renomei para init. E então fiz rootfs.cpio e criei minha imagem do sistema operacional. Mas isso também não funcionou.

Perguntas Por que o código não está sendo executado corretamente no meu próprio sistema de arquivos (parcial)?

O código depende de alguns outros arquivos ou bibliotecas dinâmicas (que estão presentes no sistema de arquivos completo)? Por que meus arquivos criados manualmente não estão funcionando?

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <fcntl.h>
    #include <signal.h>
    int main( )
    {
        extern char *optarg;
        char *cptr;
        int gpio_value = 0;
        int nchannel = 0;

        int c;
        int i;

        opterr = 0;

int argc=5;
char *argv;
char *argv2[] = {"gpio-demo", "-g", "255", "o", "0"}; argv = argv2; 
        while ((c = getopt(argc, argv, "g:io:ck")) != -1) {
            switch (c) {
                case 'g':
                    gl_gpio_base = (int)strtoul(optarg, &cptr, 0);
                    if (cptr == optarg)
                        usage(argv[0]);
                    break;
                case 'i':
                    gpio_opt = IN;
                    break;
                case 'o':
                    gpio_opt = OUT;
                    gpio_value = (int)strtoul(optarg, &cptr, 0);
                    if (cptr == optarg)
                        usage(argv[0]);
                    break;
                case 'c':
                    gpio_opt = CYLON;
                    break;
                case 'k':
                    gpio_opt = KIT;
                    break;
                case '?':
                    usage(argv[0]);
                default:
                    usage(argv[0]);

            }
        }

        if (gl_gpio_base == 0) {
            usage(argv[0]);
        }

        nchannel = open_gpio_channel(gl_gpio_base);
        signal(SIGTERM, signal_handler); /* catch kill signal */
        signal(SIGHUP, signal_handler); /* catch hang up signal */
        signal(SIGQUIT, signal_handler); /* catch quit signal */
        signal(SIGINT, signal_handler); /* catch a CTRL-c signal */
        switch (gpio_opt) {
            case IN:
                set_gpio_direction(gl_gpio_base, nchannel, "in");
                gpio_value=get_gpio_value(gl_gpio_base, nchannel);
                fprintf(stdout,"0x%08X\n", gpio_value);
                break;
            case OUT:
                set_gpio_direction(gl_gpio_base, nchannel, "out");
                set_gpio_value(gl_gpio_base, nchannel, gpio_value);
                break;
            case CYLON:
    #define CYLON_DELAY_USECS (10000)
                set_gpio_direction(gl_gpio_base, nchannel, "out");
                for (;;) {
                    for(i=0; i < ARRAY_SIZE(cylon); i++) {
                        gpio_value=(int)cylon[i];
                        set_gpio_value(gl_gpio_base, nchannel, gpio_value);
                    }
                    usleep(CYLON_DELAY_USECS);
                }
            case KIT:
    #define KIT_DELAY_USECS (10000)
                set_gpio_direction(gl_gpio_base, nchannel, "out");
                for (;;) {
                    for (i=0; i<ARRAY_SIZE(kit); i++) {
                        gpio_value=(int)kit[i];
                        set_gpio_value(gl_gpio_base, nchannel, gpio_value);
                    }
                    usleep(KIT_DELAY_USECS);
                }
            default:
                break;
        }
        close_gpio_channel(gl_gpio_base);
        return 0;
    }
    
por user2799508 19.04.2014 / 16:34

1 resposta

2

/sys é um sistema de arquivos especial. Você não pode simplesmente criá-lo e colocar arquivos nele. É como /proc , um sistema de arquivos falso fornecido pelo kernel.

Obter /sys funcionando requer duas coisas:

  1. Na configuração do seu kernel, você precisa ter CONFIG_SYSFS=y .
  2. Você precisa montá-lo com mount -t sysfs none /sys (supondo que esteja executando a partir de um initramfs desde que você mencionou cpio ) .

Assim, o próprio diretório deve estar lá para que você possa montá-lo, mas não é nada nele.

    
por 19.04.2014 / 22:27

Tags