Я пытаюсь установить Pin G11 на NanoPi Neo, ранее настроенный как вход, для вывода на C++ путем сопоставления регистра функции PIO в виртуальной памяти с mmap
и установки одного бита.Как установить GPIO NanoPi как выход на аппаратном уровне?
Per Allwinner H3 Datasheet указаны следующие аппаратные адреса:
PIO Base Адрес: 0x01C20800 (стр. 316)
PG Настройка Регистрация 1 смещение: 0xDC (стр. 338)
PG11 бит: 14:12
Как и в регистре функций малины Pi, Pin знает как минимум два состояния:
000: input
001: output
В моем сценарии, я поэтому пытается установить 12-й бит PG Настройка регистра 1. Вот мой C++ код:
struct peripheral {
unsigned long addr_hardware;
int map_size;
int mem_fd;
void *mem_map;
volatile unsigned long *addr_virtual;
int map() {
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC)) < 0) return -1;
// map addr_hardware=0x01C20000 into /dev/mem
if ((mem_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, addr_hardware)) == MAP_FAILED) return -1;
// store virtual address with offset of 0x800, which was rounded down before
addr_virtual = (volatile unsigned long *) mem_map + 0x800;
return 0;
};
void unmap() {
munmap(mem_map, map_size);
close(mem_fd);
};
};
int main() {
// initialize peripheral at rounded down PIO base address
peripheral gpio {0x01C20000, 4096 * 10};
// map PIOs into virtual memory
if (gpio.map() == -1) return -1;
// output current value of PG Configure Register 1
cout << bitset<32>(*(gpio.addr_virtual + 0xDC)) << endl;
// set 12th bit
*(gpio.addr_virtual + 0xDC) |= (1 << 12);
// output value of register after setting the 12th bit
cout << bitset<32>(*(gpio.addr_virtual + 0xDC)) << endl;
gpio.unmap();
return 0;
}
К сожалению, мой код не работает. Когда я снова запускаю сценарий, содержимое регистра конфигурации PIO изменилось на прежнее состояние. Когда я настраиваю Pin G11 как Output (через WiringNP), отображаемое значение не изменяется. Я проверяю правильную функциональность своего кода со светодиодом (он должен включаться, когда состояние изменяется с IN на OUT, потому что оно установлено на HIGH).
Когда я изменить map_size
, я получаю следующие результаты (пробелы добавлены для лучшей читаемости):
> gpio {0x01C20000, 4096 * 2}
< 00000000 00000000 00000000 00000000
< 00000000 00000000 00010000 00000000
> gpio {0x01C20000, 4096 * 10}
< 00000000 00000000 00000000 00110011
< 00000000 00000000 00000000 00110011
Я ожидаю следующий результат:
> gpio {0x01C20000, 4096 * 10}
< 00000000 00000000 00000000 00110011
< 00000000 00000000 00010000 00110011