Jump to content

    

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

 

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites

Ясно.

 

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

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

Share this post


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

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

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

Share this post


Link to post
Share on other sites
Ясно.

 

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

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

 

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

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

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

 

В частности:

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

 

 

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

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

 

Edited by Tarbal

Share this post


Link to post
Share on other sites

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

 

Share this post


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

Share this post


Link to post
Share on other sites

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

 

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

Share this post


Link to post
Share on other sites
Днем у меня доступа к сорцам не было :).

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

вот так пишу

    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

Share this post


Link to post
Share on other sites

Я пишу так:

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

Share this post


Link to post
Share on other sites
Каким компилятором - компилировать модули ядра? Тем, которым собирается ядро под target-платформу ?

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

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

 

Share this post


Link to post
Share on other sites
Я пишу так:

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

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this