Чтение из регистра процессора Allwinner H3 ARM

#include <stdint.h>
#include <stddef.h>
#include <stdio.h>


static void foo(void){
    volatile  uint32_t *temp_addr;
    temp_addr = (uint32_t*)(0x01C20C00);
    *temp_addr =0;
}
int main(){
    tinit();

};

Он компилируется, но в результате возвращает сообщение Segmentation fault. Я просто хочу сбросить все биты в регистре 0x01c200c00.

введите здесь описание изображения


person rd1337    schedule 15.01.2020    source источник
comment
Что в 0x01C20C00?   -  person dragosht    schedule 15.01.2020
comment
Я только что добавил часть таблицы.   -  person rd1337    schedule 15.01.2020
comment
Верно. Но вы запускаете это из пользовательского пространства Linux. Вы получаете Segmentation fault, потому что этот адрес не отображается в памяти процесса.   -  person dragosht    schedule 15.01.2020
comment
я просто компилирую эту программу на терминале своего устройства, которое содержит именно этот процессор. Я делаю это неправильно?   -  person rd1337    schedule 15.01.2020
comment
Как обычный пользователь, у вас нет доступа к оборудованию, насколько я знаю. Вот что сказал @dragosht.   -  person the busybee    schedule 15.01.2020
comment
Подумайте об этом так: у вас есть kernel-space и user-space, где kernel-space защищено от всего, что происходит в пространство пользователя. Это функция безопасности, защищающая ядро ​​от любых ошибочных или вредоносных процессов в пользовательском пространстве. (теперь есть механизм повышения привилегий, который позволяет коду пространства пользователя взаимодействовать с процессами пространства ядра). Вы пытаетесь получить доступ к адресу kernel-space TIMER напрямую, минуя все средства защиты kernel-space. Это не сработает (если бы это сработало, не было бы разделения между kernel-space и user-space).   -  person David C. Rankin    schedule 15.01.2020
comment
Ядро и библиотека времени выполнения, вероятно, обеспечивают возможность корректного взаимодействия с этим таймером, включая соответствующий заголовок и используя одну из предоставленных функций таймера. Поиск адреса таймера и попытка доступа к нему напрямую, скорее всего, не удастся по причинам, изложенным выше. Введите apropos timer в окне консоли, чтобы просмотреть список доступных функций таймера: getitimer, settimer, timer_create, ...   -  person David C. Rankin    schedule 15.01.2020
comment
вам нужно будет написать драйвер ядра, использовать mmap() или, если инструменты/библиотеки уже доступны для этого процессора/платформы, используйте их (сначала, поскольку они будут мешать всему, что вы пытаетесь попробовать).   -  person old_timer    schedule 15.01.2020
comment
Какова именно ваша конечная цель? Если вы хотите поэкспериментировать на низком уровне с аппаратным обеспечением H3 в учебных целях, запуская программы на «голом железе» из u-boot, загружая их с помощью команды loadb или напрямую загружая на H3 с помощью USB и sunxi-fel — это то, что вам нужно. Если вы хотите узнать, как взаимодействовать/использовать оборудование H3 в Linux, вам уже ответили в комментариях выше, и вы можете посмотреть код драйвера таймера H3 для Linux здесь.   -  person Frant    schedule 15.01.2020
comment
Если вы хотите узнать больше об аппаратной абстракции в Linux. Книга охватывает Linux 2.6.x, но основные концепции, я думаю, все еще актуальны.   -  person Frant    schedule 15.01.2020


Ответы (1)


Ваша программа не работает, потому что 0x01C20C00 — это физический адрес, а ваша программа использует виртуальные адреса. Для экспериментов вы можете получить доступ к GPIO, таймерам или другим периферийным устройствам без написания драйвера ядра. Для этого вам нужно создать отображение памяти, например:

#define ALLWINNER_TIMER_BASE 0x01C20C00

struct allwinner_timer
{
  volatile uint32_t IRQ_EN_REG;
  // add other registers from the datasheet, or find a kernel driver source with these definitions
};

int fd = open("/dev/mem", O_RDWR);
struct allwinner_timer *t = (struct allwinner_timer *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, ALLWINNER_TIMER_BASE);
// TODO: check for errors
t->IRQ_EN_REG = 0;

Обратите внимание, что:

  • Это может не сработать, если ядро ​​ограничивает доступ к /dev/mem. Это можно узнать, просмотрев параметры ядра, например. CONFIG_STRICT_DEVMEM и с dmesg;
  • Очевидно, он должен работать под суперпользователем;
  • Ваш код может мешать другим частям системы, например. драйверы ядра обращаются к одному и тому же периферийному устройству, что приводит к непредсказуемым результатам.
person A.K.    schedule 15.01.2020