разработка и программирование электронных устройств

Сборка инструментария ARM Toolchain (arm-none-eabi) в Fedora Linux

В дистрибутиве Fedora Electronic Lab отсутствует инструментарий для кросс-компиляции standalone программ для платформы ARM. Есть возможность установки этого инструментария в качестве дополнительного пакета с помощью yum install. Но установленный в результате инструментарий будет устаревшим.

В этой статье я расскажу как самостоятельно собрать инструментарий для программирования микроконтроллеров ARM . Это гарантирует вам наличие самых свежих версий программ, входящих в пакет.

  1. Сначала необходимо загрузить и разархивировать самые свежие версии исходных кодов необходимых утилит. В следующей таблице указаны названия программ и ссылки на источники для загрузки.
  2. № п/п Название пакета Ссылка для загрузки
    1 binutils http://ftp.gnu.org/gnu/binutils/
    2 newlib ftp://sourceware.org/pub/newlib/index.html
    3 gcc http://gcc.gnu.org/mirrors.html
    4 gdb http://ftp.gnu.org/gnu/gdb/

    Распаковку осуществляем утилитой tar с соответствующими ключами.

    cd 
    cd downloads
    tar -xjvf  filename.tar.bz2  
    tar -xzvf filename.tar.gz

    Создаем в своем рабочем каталоге подкаталог build , копируем в него загруженные файлы.

    cd
    mkdir build
    cd /home/user/downloads
    cp -r binutils-version /home/user/build
    cp -r newlib-version /home/user/build
    cp -r gcc-version /home/user/build
    cp -r gdb-version /home/user/build
  3. Устанавливаем дополнительные программы и библиотеки, которые будут необходимы при сборке инструментария.
  4. su
    yum -y install flex bison gmp-devel mpfr-devel ncurses-devel libmpc-devel autoconf texinfo-tex zlib-devel expat expat-devel
    yum -y groupinstall “Development Tools”
  5. Выполняем конфигурирование и сборку пакета binutils.
  6. cd /home/user/build
     cd binutils-version
    ./configure –target=arm-none-eabi –prefix=/home/user –enable-interwork –enable-multilib –disable-nls –disable-libssp
    make all
    make install
    cd ..
  7. Теперь выполним первую сборку кросс-компилятора arm-none-eabi-gcc без стандартной библиотеки языка C (newlib). Кросс-компилятор нам как раз и нужен для того, чтобы собрать эту-самую библиотеку. После сборки newlib выполняется повторная сборка кросс-компилятора уже вместе с библиотекой.
  8. cd gcc-version
    mkdir objdir
    cd objdir
    ../configure –target=arm-none-eabi –prefix=/home/user –enable-interwork –enable-multilib –enable-languages=”c,c++” --with-newlib –with-headers=../../newlib-version/newlib/libc/include/ –disable-libssp –disable-nls –with-system-zlib
    make all-gcc
    make install-gcc
    cd ../..
  9. После сборки кросс-компилятора приступим к компиляции библиотеки newlib. Это версия стандартной библиотеки языка C для встраиваемых систем. В стандартной библиотеке используются системные вызовы операционной системы. В нашем варианте ОС нет, поэтому для системных вызовов пишутся соответствующие программные заглушки. Также библиотека использует стандартные функции динамического выделения и освобождения памяти malloc и free , что может привести к фатальным ошибках в программах для микроконтроллеров. Скомпилировав библиотеку с ключем -DMALLOC_PROVIDED можно реализовать динамическое выделение памяти самостоятельно.
  10. cd newlib-version
    ./configure –target=arm-none-eabi –prefix=/home/user –enable-interwork –enable-multilib –disable-libssp –disable-nls –disable-shared –disable-newlib-supplied-syscalls
    make CFLAGS_FOR_TARGET=”-DMALLOC_PROVIDED -D__BUFSIZ__=64 -ffunction-sections -fdata-sections”
    make install
    cd ..
  11. Теперь необходимо собрать финальную версию кросс-компилятора.
  12. cd gcc-version/objdir
    make all
    su
    make install
    exit
    cd ../..
  13. Устанавливаем отладчик gdb.
  14. cd gdb-version
    ./configure –target=arm-none-eabi –prefix=/home/user –enable-interwork –enable-multilib –disable-nls –disable-libssp
    make all
    su
    make install
    exit

После установки каталог build вместе с его содержимым можно удалить

cd
rm -frv build

Проверить версии установленных утилит можно с помощью ключа –version.

#arm-none-eabi-gcc –version
arm-none-eabi-gcc (GCC) 4.8.2
Copyright © 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. 
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Собранный кросс-компилятор также поддерживает аппаратный сопроцессор FPU , который , например, имеется в ядре cortex-m4.

#arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard

При создании новых проектов нужно иметь ввиду, что реализация системных вызовов библиотеки newlib полностью возложена на вас. Также необходимо реализовать библиотечные функции malloc и free. Если вы используете в своем проекте FreeeRTOS, то последние могут вызывать функции выделения(освобождения) памяти из статического массива FreeRTOS.

Пример такого файла приведен ниже.

#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <string.h>
 
#undef errno
extern int errno;
extern int __io_putchar(int ch) __attribute__((weak));
extern int __io_getchar(void) __attribute__((weak));
 
register char * stack_ptr asm("sp");
 
char *__env[1] = { 0 };
char **environ = __env;
 
void initialise_monitor_handles()
{
}
int _getpid(void)
{
	return 1;
}
int _kill(int pid, int sig)
{
	errno = EINVAL;
	return -1;
}
void _exit (int status)
{
	_kill(status, -1);
	while (1) {}		/* Make sure we hang here */
}
int _read (int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx < len; DataIdx++)
	{
	  *ptr++ = __io_getchar();
	}
 
return len;
}
int _write(int file, char *ptr, int len)
{
	int DataIdx;
 
	for (DataIdx = 0; DataIdx  stack_ptr)
	{
		errno = ENOMEM;
		return (caddr_t) -1;
	}
	heap_end += incr;
	return (caddr_t) prev_heap_end;
}
caddr_t _sbrk(int incr)
{
	extern char end asm("end");
	static char *heap_end;
	char *prev_heap_end;
 
	if (heap_end == 0)
		heap_end = &end;
 
	prev_heap_end = heap_end;
	if (heap_end + incr > stack_ptr)
	{
		errno = ENOMEM;
		return (caddr_t) -1;
	}
 
	heap_end += incr;
 
	return (caddr_t) prev_heap_end;
}
int _close(int file)
{
	return -1;
}
int _fstat(int file, struct stat *st)
{
	st->st_mode = S_IFCHR;
	return 0;
}
int _isatty(int file)
{
	return 1;
}
int _lseek(int file, int ptr, int dir)
{
	return 0;
}
int _open(char *path, int flags, ...)
{
	/* Pretend like we always fail */
	return -1;
}
int _wait(int *status)
{
	errno = ECHILD;
	return -1;
}
int _unlink(char *name)
{
	errno = ENOENT;
	return -1;
}
int _times(struct tms *buf)
{
	return -1;
}
int _stat(char *file, struct stat *st)
{
	st->st_mode = S_IFCHR;
	return 0;
}
int _link(char *old, char *new)
{
	errno = EMLINK;
	return -1;
}
int _fork(void)
{
	errno = EAGAIN;
	return -1;
}
int _execve(char *name, char **argv, char **env)
{
        errno = ENOMEM;
	return -1;
}
void _init (void)
{
}
void _fini (void)
{
}

При использовании FreeRTOS в этот файл можно дописать реализацию функций malloc и free на основе аллокатора FreeRTOS.

#include "FreeRTOS.h"
 
_PTR _DEFUN (malloc, (nbytes), size_t nbytes)
{
	return _malloc_r (_REENT, nbytes);
}
void _DEFUN (free, (aptr), _PTR aptr)
{
	_free_r (_REENT, aptr);
}
_PTR _malloc_r(struct _reent *re, size_t size)
{
	return pvPortMalloc(size);
}
_VOID _free_r(struct _reent *re, _PTR ptr)
{
	vPortFree(ptr);
}

3 Comments to Сборка инструментария ARM Toolchain (arm-none-eabi) в Fedora Linux

  1. Volldemar's Gravatar Volldemar
    23 декабря 2013 at 10:20 | Permalink

    В дистрибутиве Arch Linux, это делается следующим образом:
    $ yaourt -S arm-none-eabi-binutils
    $ yaourt -S arm-none-eabi-gcc
    $ yaourt -S arm-none-eabi-gdb
    #pacman -S eclipse eclipse-cdt openocd
    Поясню, почему в три стирочки установка из аура, так как компиляция довольно длительное дело и может закончиться ошибкой, я предпочитаю выполнять по шагам, а не кучей. А вот установку пакманом можно уже выполнять в пакетном режиме.

    После всех этих «многочисленных» телодвижений, получаем:
    $ arm-none-eabi-gcc –version
    arm-none-eabi-gcc (Arch User Repository) 4.8.2
    Copyright (C) 2013 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions. There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    $ arm-none-eabi-gcc -print-multi-lib
    .;
    thumb/arm7tdmi-s;@mthumb@mcpu=arm7tdmi-s
    thumb/cortex-m0;@mthumb@mcpu=cortex-m0
    thumb/cortex-m3;@mthumb@mcpu=cortex-m3
    thumb/cortex-m4;@mthumb@mcpu=cortex-m4
    thumb/cortex-m4/float-abi-hard/fpuv4-sp-d16;@mthumb@mcpu=cortex-m4@mfloat-abi=hard@mfpu=fpv4-sp-d16

    $ openocd –version
    Open On-Chip Debugger 0.7.0 (2013-11-25-15:57)
    Licensed under GNU GPL v2

  2. Volldemar's Gravatar Volldemar
    23 декабря 2013 at 11:42 | Permalink

    В данном случае, устанавливаемое из АУР-а скачивается со следующих источников:
    ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
    ftp://sourceware.org/pub/newlib/newlib-2.0.0.tar.gz

    Куда уж болле официально? ;)

Leave a Reply

You must be logged in to post a comment.