Atridies 0 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Под плату SBC8600 (AM3359, Angstrom Linux) делаю программу. Есть Toolchain, и есть tools: для сборки ядра, u-boot и пр. под эту плату. Пока используются стандартные функции Си - то все нормально: ПО компилится Toolchain-ом, нормально запускается и работает. Но сейчас понадобился прямой доступ к регистрам микроконтроллера. Хочу сделать это так: base = ioremap(ADDR, SIZE); __raw_writel(base+0x08F0, DATA); x = __raw_readl(base+0x08F0); Но этот код не хочет компилироваться. Эти функции - принадлежат ядру и находятся в файлах: /arch/arm/include/asm/io.h. В самой Toolchain - нету такого файла и нету таких функций. Оно наверное и понятно - Toolchain вряд ли поддерживает функции ядра. Подключил к своему проекту h-файл из tools для сборки ядра - все равно не компилится: у меня ведь проект ядра не компилируется вместе с программой. Что делать - не знаю. Как вообще компилироваться - если используются функции ядра ? P.S. Пробовал сделать это через /dev/mem и mmap - все получается, но работает только на чтение. Записать не получается. Заранее спасибо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
krux 8 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба капитан очевидность какбы подсказывает: функции ядра можно использовать только в ядре. (в kernel-space) если вам надо работать с железом напрямую - то в линукс это возможно только в ядерном модуле, т.е. в драйвере. из простого ПО (user-space) прямой доступ к железу не предусматривался, и противоречит философии linux. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Atridies 0 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Ясно. А как писать и компилировать драйверы ? Как писАть сами драйверы - я читал несколько статей, думаю разберусь. А вот как компилить (Cross Compilatioin)? Надо использовать tools для сборки ядра ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jury093 2 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба P.S. Пробовал сделать это через /dev/mem и mmap - все получается, но работает только на чтение. Записать не получается. покажите кусок кода - как вы инициализуете доступ и как обращаетесь.. с правами рута все прекрасно ммапится, читается и пишется (по крайней мере на архитектурах freescale, ti, pxa, atmel) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Tarbal 4 31 июля, 2015 Опубликовано 31 июля, 2015 (изменено) · Жалоба Ясно. А как писать и компилировать драйверы ? Как писАть сами драйверы - я читал несколько статей, думаю разберусь. А вот как компилить (Cross Compilatioin)? Надо использовать tools для сборки ядра ? Кросс компиляцию уже обсуждали: Сделайте поиск в форуме по ключевуму слову "eabi" Будут вопросы спрашивайте. В частности: http://electronix.ru/forum/index.php?showt...=eabi&st=45 Одно из лучших руководств по напиасанию драйверов: http://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf Изменено 31 июля, 2015 пользователем Tarbal Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Atridies 0 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Вот попытка записать данные напрямую в память - через /dev/mem. int mfd; void * base; int regData; char str[100]; mfd = open("/dev/mem", O_RDWR); if( mfd < 0 ) { printf("Cannot open /dev/mem.\n"); return 0; } printf("/dev/mem opened.\n"); base = mmap(0, 0x00001000, PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0x44E10000); if (base == MAP_FAILED) { printf("Memory mapping error.\n"); return 0; //exit(EXIT_FAILURE); } printf("Memory block mapped at address %p.\n", base); regData = *((unsigned int*)(base + 0x0)); sprintf(str, "Revision = 0x%X", regData); puts(str); regData = *((unsigned int*)(base + 0x600)); sprintf(str, "Device ID = 0x%X", regData); puts(str); regData = *((unsigned int*)(base + 0x604)); sprintf(str, "Dev. feature = 0x%X", regData); puts(str); regData = *((unsigned int*)(base + 0x8F0)); sprintf(str, "Pin MMC0_DAT3 = 0x%X", regData); puts(str); *((unsigned int*)(base + 0x8F0)) = 0x34; sprintf(str, "Set pin MMC0_DAT3 = uart1_dcdn"); puts(str); regData = *((unsigned int*)(base + 0x8F0)); sprintf(str, "Pin MMC0_DAT3 = 0x%X", regData); puts(str); munmap(0, 0x00001000); return 0; Проц: AM3359. В доке на него - указано, что запись в эти регистры может быть только в "privileged mode". Это от рута - или что-то другое ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jury093 2 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Вот попытка записать данные напрямую в память - через /dev/mem. Проц: AM3359. В доке на него - указано, что запись в эти регистры может быть только в "privileged mode". Это от рута - или что-то другое ? если бы днем выложили сорц, то прямо на ам3359 и посмотрел бы что не так.. да, все действия от рута, иначе любой юзер завалит систему одним движением.. вот куски из рабочего кода (запускал на nuc950), с коррекцией адресов пойдет на другой АРМ-архитектуре #define XZ_BA 0xB0000000 #define MAP_BASE1 (XZ_BA) #define MAP_SIZE 4096Ul #define MAP_MASK (MAP_SIZE - 1) int fd; void *mapped_base1; if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) { printf("Cannot open /dev/mem.\n"); exit(EXIT_FAILURE); } printf("/dev/mem opened.\n"); mapped_base1 = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, MAP_BASE1 & ~MAP_MASK); if (mapped_base1 == (void *) -1) { printf("Memory mapping error.\n"); exit(EXIT_FAILURE); } printf("Check register MFSEL\n"); mapped_base1+=(MAP_BASE1 & MAP_MASK); printf("Target address mapped 0x%08x-->0x%08x\n",(int) MAP_BASE1,(int)mapped_base1); data = *(int*)(mapped_base1+0x00); printf("PDID =%08X\n",data); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Atridies 0 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Днем у меня доступа к сорцам не было :). Ваш код - только читает из памяти. Это у меня тоже получается. У меня писАть не получается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jury093 2 31 июля, 2015 Опубликовано 31 июля, 2015 · Жалоба Днем у меня доступа к сорцам не было :). Ваш код - только читает из памяти. Это у меня тоже получается. У меня писАть не получается. вот так пишу data = *(int*)(mapped_base1+0x0c); data = data & 0xffffdbff; *(int*)(mapped_base1+0x0c) = data; printf("MFSEL =%08X\n",data); это отладочный код, я его таскаю по всем платформам, всегда работает.. А как писать и компилировать драйверы ? Как писАть сами драйверы - я читал несколько статей, думаю разберусь. А вот как компилить (Cross Compilatioin)? Надо использовать tools для сборки ядра ? я с нуля драйверы не писал, но знаю пару вариантов: - в дереве исходников своего ядра находится близкоподходящий драйвер под свои нужды, клонируется под другим именем и прописывается в конфигурацию, потом меняется функционал под свое железо или алгоритм - многие компании-производители, в частности сетевых железяк, практикуют выкладывать пакет с исходниками драйверов под свои адаптеры/сетевые чипы - архив разворачивается, внутри правятся пути до исходников текущего ядра, далее сборка кросскомпилятором и получается модуль драйвера *.ko, который можно подгрузить в ядро для написания с нуля, вместо клонирования, создаете свой сишный файл в подходящем разделе дерева драйверов, прописываете в конфигурацию, потом долго и нудно изобретаете свои код, для обмена данными между железом и юзерспейсом, *.ko - профит.. в общем случае сетапиться линукс система (реальная или в виртуалке), на нее разворачивается дерево исходников ядра и архив с кросскомпилятором (aka тулчейн). в частности, для ам3359 можно раздобыть все в одном флаконе на ti.com или профильных форумах/комьюнити.. если накопитель на таргете (ам3359) большой и шустрый, то ядро можно собрать прямо в системе, не заморачиваясь х86 хостом и КК.. А вот как компилить (Cross Compilatioin)? не вижу смысла пересказывать 100 раз описанное, почитайте на том же ti.com местную twiki для am3359 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Atridies 0 1 августа, 2015 Опубликовано 1 августа, 2015 · Жалоба Я пишу так: *((unsigned int*)(base + 0x8F0)) = 0x34; Собственно в регистры, не защищенные privileged режимом - все пишется нормально. Но конкретно нужные мне: "For writing to the control module registers, the Cortex A8 MPU will need to be in privileged mode of operation and writes will not work from user mode." Поэтому и не пишется.... не вижу смысла пересказывать 100 раз описанное, почитайте на том же ti.com местную twiki для am3359 Я вероятно неправильно задал вопрос. Каким компилятором - компилировать модули ядра? Тем, которым собирается ядро под target-платформу ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_3m 9 1 августа, 2015 Опубликовано 1 августа, 2015 · Жалоба Каким компилятором - компилировать модули ядра? Тем, которым собирается ядро под target-платформу ? Да, тем которым собирали ядро под target. Еще понадобятся заголовки ядра. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Jury093 2 3 августа, 2015 Опубликовано 3 августа, 2015 · Жалоба Я пишу так: *((unsigned int*)(base + 0x8F0)) = 0x34; Собственно в регистры, не защищенные privileged режимом - все пишется нормально. Но конкретно нужные мне: Поэтому и не пишется.... да, вы правы, действительно не пишется.. впрочем, народ это бодро обходит, по крайней мере для gpio. (насколько я помню, если в борд-файле не прописать нужный пин в gpio mode, то потом фиг его настроишь..) но вот тут вроде как через debugfs крутят: http://graycat.io/tutorials/beaglebone-io-using-python-mmap/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться