В дистрибутиве Fedora Electronic Lab отсутствует инструментарий для кросс-компиляции standalone программ для платформы ARM. Есть возможность установки этого инструментария в качестве дополнительного пакета с помощью yum install. Но установленный в результате инструментарий будет устаревшим.
В этой статье я расскажу как самостоятельно собрать инструментарий для программирования микроконтроллеров ARM . Это гарантирует вам наличие самых свежих версий программ, входящих в пакет.
- Сначала необходимо загрузить и разархивировать самые свежие версии исходных кодов необходимых утилит. В следующей таблице указаны названия программ и ссылки на источники для загрузки.
- Устанавливаем дополнительные программы и библиотеки, которые будут необходимы при сборке инструментария.
- Выполняем конфигурирование и сборку пакета binutils.
- Теперь выполним первую сборку кросс-компилятора arm-none-eabi-gcc без стандартной библиотеки языка C (newlib). Кросс-компилятор нам как раз и нужен для того, чтобы собрать эту-самую библиотеку. После сборки newlib выполняется повторная сборка кросс-компилятора уже вместе с библиотекой.
- После сборки кросс-компилятора приступим к компиляции библиотеки newlib. Это версия стандартной библиотеки языка C для встраиваемых систем. В стандартной библиотеке используются системные вызовы операционной системы. В нашем варианте ОС нет, поэтому для системных вызовов пишутся соответствующие программные заглушки. Также библиотека использует стандартные функции динамического выделения и освобождения памяти malloc и free , что может привести к фатальным ошибках в программах для микроконтроллеров. Скомпилировав библиотеку с ключем -DMALLOC_PROVIDED можно реализовать динамическое выделение памяти самостоятельно.
- Теперь необходимо собрать финальную версию кросс-компилятора.
- Устанавливаем отладчик gdb.
№ п/п | Название пакета | Ссылка для загрузки |
1 | binutils | https://ftp.gnu.org/gnu/binutils/ |
2 | newlib | ftp://sourceware.org/pub/newlib/index.html |
3 | gcc | https://gcc.gnu.org/mirrors.html |
4 | gdb | https://ftp.gnu.org/gnu/gdb/ |
Распаковку осуществляем утилитой tar с соответствующими ключами.
1 2 3 4 |
cd cd downloads tar -xjvf filename.tar.bz2 tar -xzvf filename.tar.gz |
Создаем в своем рабочем каталоге подкаталог build , копируем в него загруженные файлы.
1 2 3 4 5 6 7 |
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 |
1 2 3 |
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” |
1 2 3 4 5 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 .. |
1 2 3 4 5 6 7 |
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 ../.. |
1 2 3 4 5 |
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 .. |
1 2 3 4 5 6 |
cd gcc-version/objdir make all su make install exit cd ../.. |
1 2 3 4 5 6 |
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 вместе с его содержимым можно удалить
1 2 |
cd rm -frv build |
Проверить версии установленных утилит можно с помощью ключа —version.
1 2 3 4 5 |
#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.
1 2 3 4 |
#arm-none-eabi-gcc -print-multi-lib .; thumb;@mthumb fpu;@mfloat-abi=hard |
При создании новых проектов нужно иметь ввиду, что реализация системных вызовов библиотеки newlib полностью возложена на вас. Также необходимо реализовать библиотечные функции malloc и free. Если вы используете в своем проекте FreeeRTOS, то последние могут вызывать функции выделения(освобождения) памяти из статического массива FreeRTOS.
Пример такого файла приведен ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
#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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#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); } |
Viewed 51293 times by 10583 viewers
Comments
В дистрибутиве 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
yaourt — это пакетный менеджер, который является надстройкой над pacman и предоставляющий возможность поиска и установки программ из AUR.
AUR (ArchLinux User-community Repository (AUR))- это репозиторий, который официально не поддерживается и формируется самими пользователями Archlinux.
В Fedora тоже можно установить arm-none-eabi из репозитория, однако в репозитории находиться пакет Sourcery G++ Lite под Linux, который далеко не самый свежий.
В ArchLinux в репозиториях AUR находятся самые свежие пакеты. Насколько я понимаю из-за того, что они не официальные.
В данном случае, устанавливаемое из АУР-а скачивается со следующих источников:
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
Куда уж болле официально? 😉