LINUX.ORG.RU

OpenWrt GPIO MT7620A

 , ,


0

2

Всем хелоу!

С целью лучше разобраться, как устроен linux, я пытаюсь сделать хобби проект на openwrt. У меня есть роутер asus rt-ac51u, на который ставится openwrt и у него есть uart выведенный на плату. В даташите на микропроцессор мт7620а, который стоит в моем роутере, описана такая интересная фича, как port multiplexing, и там производитель пишет что uart можно использовать, как gpio. Этого я и добиваюсь. В мт7620а есть системный регистр GPIOMODE[31:0] в котором мне надо записать 1 в 5й бит. Но как это сделать?
На форуме openwrt мне посоветовали копать в сторону .dts файлов, и там определять этот регистр (линк).
Может кто-нибудь подсказать, как мне использовать dts файл для этого? Или может есть, какой-то другой путь записать число в системный регистр микропроцессора?

ЗЫ: Описание device tree source на kernel.org выглядит, как китайская грамота.

производитель пишет что uart можно использовать, как gpio

в SoC пины имеют по несколько назначений, у них есть мультиплексор (коммутатор по русски) который можно переключить на один из подключенных контроллеров, в данном случае UART или GPIO

В мт7620а есть системный регистр GPIOMODE[31:0] в котором мне надо записать 1 в 5й бит. Но как это сделать?

если это хобби проект или нет желания/возможности разбираться с правильным путем - «копать в сторону .dts файлов», можно использовать грязный хак. Отобразить нужные регистры в адресном пространстве пользователя и записать в регистры коммутатора нужные значения. Вот примердля маппинга 16 кб

#define MAP_SIZE 0x4000UL /* 16K */
#define MAP_MASK (MAP_SIZE - 1)

void *mmap_16K(unsigned long paddr)
{
        int fd;
        void *map_base;

        if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
                printf("/dev/mem could not be opened.\n");
                perror("open");
                return (void *) -1;
        }

        map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
                fd, (off_t)(paddr & ~MAP_MASK));
        if (map_base == (void *) -1) {
                printf("Memory map failed.\n");
                perror("mmap");
        }

        close(fd);

        return map_base;
}

int munmap_16K(void *map_base)
{
        if (munmap(map_base, MAP_SIZE) == -1) {
                printf("Memory unmap failed.\n");
                return 1;
        }

        return 0;
}

paddr - физический адрес регистров - нужно найти в даташите, только учитывать что мапить надо не конкретный регистр а весь блок регистров в котрый он входит, а потом вычислить его смещение относительно начала этого блока. Блоки регистров выровнены по границе 4 кб как правило на SoC c 32-битными ядрами. После этого можно использовать интерфейс для доступа к GPIO через sysfs. Консоль отключать не нужно как тебе там посоветовали - после переклчения мультиплексора консольный UART уже не имеет доступ к этими пинам.

anonymous ()
Ответ на: комментарий от anonymous

Отобразить нужные регистры в адресном пространстве пользователя и записать в регистры коммутатора нужные значения

Сейчас подумаю как это сделать.
Адрес регистра известен -> BASE: 0x1000_0000 OFFSET: 0x0060

WorldDestroyer ()
Ответ на: комментарий от WorldDestroyer

Анон выше толково посоветовал, но это грязный хак. С его помощью можно проверить, сработает ли коммутация регистров нужным образом. Если сработает — можно будет модифицировать .dts и сделать всё по уму.

TwisteR ★★ ()