Перейти к содержанию
    

Компиляция ПО под embedded. Непонятно как поступить.

Под плату 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 - все получается, но работает только на чтение. Записать не получается.

 

Заранее спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

капитан очевидность какбы подсказывает:

функции ядра можно использовать только в ядре. (в kernel-space)

если вам надо работать с железом напрямую - то в линукс это возможно только в ядерном модуле, т.е. в драйвере.

из простого ПО (user-space) прямой доступ к железу не предусматривался, и противоречит философии linux.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ясно.

 

А как писать и компилировать драйверы ? Как писАть сами драйверы - я читал несколько статей, думаю разберусь.

А вот как компилить (Cross Compilatioin)? Надо использовать tools для сборки ядра ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. Пробовал сделать это через /dev/mem и mmap - все получается, но работает только на чтение. Записать не получается.

покажите кусок кода - как вы инициализуете доступ и как обращаетесь..

с правами рута все прекрасно ммапится, читается и пишется (по крайней мере на архитектурах freescale, ti, pxa, atmel)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ясно.

 

А как писать и компилировать драйверы ? Как писАть сами драйверы - я читал несколько статей, думаю разберусь.

А вот как компилить (Cross Compilatioin)? Надо использовать tools для сборки ядра ?

 

Кросс компиляцию уже обсуждали:

Сделайте поиск в форуме по ключевуму слову "eabi"

Будут вопросы спрашивайте.

 

В частности:

http://electronix.ru/forum/index.php?showt...=eabi&st=45

 

 

Одно из лучших руководств по напиасанию драйверов:

http://www.tldp.org/LDP/lkmpg/2.6/lkmpg.pdf

 

Изменено пользователем Tarbal

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот попытка записать данные напрямую в память - через /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". Это от рута - или что-то другое ?

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот попытка записать данные напрямую в память - через /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);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Днем у меня доступа к сорцам не было :).

 

Ваш код - только читает из памяти. Это у меня тоже получается. У меня писАть не получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Днем у меня доступа к сорцам не было :).

Ваш код - только читает из памяти. Это у меня тоже получается. У меня писАть не получается.

вот так пишу

    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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я пишу так:

*((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-платформу ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Каким компилятором - компилировать модули ядра? Тем, которым собирается ядро под target-платформу ?

Да, тем которым собирали ядро под target.

Еще понадобятся заголовки ядра.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я пишу так:

*((unsigned int*)(base + 0x8F0)) = 0x34;

Собственно в регистры, не защищенные privileged режимом - все пишется нормально. Но конкретно нужные мне:

Поэтому и не пишется....

да, вы правы, действительно не пишется..

впрочем, народ это бодро обходит, по крайней мере для gpio.

(насколько я помню, если в борд-файле не прописать нужный пин в gpio mode, то потом фиг его настроишь..)

но вот тут вроде как через debugfs крутят:

http://graycat.io/tutorials/beaglebone-io-using-python-mmap/

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...