Адреса, которые вы назначили, выглядят как физические или шинные адреса; Ваша программа будет работать с виртуальными или программными адресами. Ядро на вашей машине создает страницы перевода, чтобы ваша программа могла поддерживать нормализованный просмотр адресов памяти, которые ядро может назначать динамически.
Вам необходимо отобразить (используя mmap ()) пространство регистров в вашей программе и назначить структуру, указывающую на них.
Вы должны получить код, который выглядит примерно так:
GPIO_TypeDef *g0, *g1, ... ;
...
g0 = mmap(0, sizeof *g0,..., fd, 0);
...
g0->DataOut = 3;
...
ps: стилистически, предварение _TypeDef побеждает назначение механизма typedef, который заключается в создании значимых имен и самодокументируемых программ. Идиотическое использование _t только немного лучше, потому что оно не тратит так много нажатий клавиш. Помните, что у некоторых программистов есть проблемы со зрением, и они должны слушать вспомогательное устройство, которое говорит «подчеркивать прописными буквами T y pe прописными буквами D e f» каждый раз, когда они сталкиваются с этим!