Цитата(alexxx86 @ Aug 14 2015, 10:34)

Мне больше не понятно другое, к примеру берем какой нибудь чужой проект с всеми исходниками и makefileом, в makefile указан тип микроконтроллера и рабочаю частота. Или другой пример, решил я почитать про bootloaded, нашел тему где все подробно расписано и есть все исходники и makefile, опять-же там указывается тип и частота. Я работаю в atmel studio 6, там автоматически генерируется makefile, но там нет таких пунктов. Вот мне и не понятно почему где-то указывается тип и частота а где-то нет.
Давайте подумаем вот на какую тему -- а на что, собственно, влияет тактовая частота процессора в программе?
Делаю паузу, чтобы Вы сам попробовали ответить на это вопрос.
Подумайте хояты минуту, прежде чем читать далее.
На скорость сборки проекта или на состав проекта (из каких файлов будет состоять прект) тактовая частота никак не влияет. Это понятно.
Тактовая частота влияет на скорость работы самой программы. Тоже абсолютно прозрачно. Однако, код, удачно откомпилированный и залитый в кремний, будет работать как с одной тактовой частотой, так и с другой с другой -- будь они различными хоть в 100 раз! Ну, какая разница с какой скоростью моргает светодиод или опрашивается кнопочка? Нехватает скорость? -- Припаяй другой кварц! Программа принципиально будет работать. Поэтому в этом и предыдущем случае задавать тактовую частоту в мэйкфайле нет ни какого смысла. Этот параметр ведь никак не будет использоваться в программе.
Другое дело, когда в вашей программе нужно четко соблюдать время и/или временные интервалы. Нпример, синхроимпульс, который вырабатывает ваше устройство должен иметь длительность ровно 100 мкс. Или последовательный порт UART должен работать на скорости 9600 бод. В этих случаях где-то в программном коде будут вычисляться коэффициенты для таймеров, для UART-ов или количество пустых циклов для программной задержки.
Есть два варианта. Первый -- вы вручную (на калькуляторе, на бумажке или еще как-нибудь) посчитли значения коэффициентов, то есть получили числовые константы и напрямую забили их в программый код. Ну, например, вы вычислили, что для задержки 100 мкс вам требуется 36 циклов. Тогда вы тупо пишите:
Код
void delay100us(void)
{
volatile uint8_t i;
for (i = 0; i <=36; i++)
; // do nothing
}
Или для того чтобы UART работал на скорости 9600 бод в регистр UBBRL нужно записать значение 49:
Код
...
UBBRL = 49;
...
В этом коде значение тактовой частоты тоже отсутствует.
Во втором случае вы можете в программе задать записать определение констатны, которая соответствует тактовой чатоте процессора. Ну, наприер:
Код
#define FCPU (7372800UL)
Тогда в программе для рассчета количества циклов и коэффициента для UBBR прямо в тексте исходного кода може использовать эту константу для вычисления нужных значений:
Код
#define FCPU (7372800UL)
#define BAUD (9600)
...
void delay100us(void)
{
volatile uint8_t i;
for (i = 0; i <= (FCPU / 324); i++)
; // do nothing
}
...
UBBRL = FCPU / (16 * BAUD) - 1;
...
Удобство в этом случае состоит в том, что теоретически вам уже не нужно вычислять все коэффициенты в ручную. Оптимизирующие компиляторы вычисления сделают за вас и в код микроконтроллера попадет уже готовое значение коэффициента. То есть компилятор сгенерирует не команды, вычичляющие коэффициент, а уже готовую констатну. Я сказал -- "теоретически". Практически же, понятное дело, лучше такие вещи все-же проконтролировать. У меня по жизни несколько раз были случаи, когда вычисления вылетали за диапазон допустимых значений. Приходилось код подправлять ручками. Собственно, в этом и состоит труд разработчика-программиста.
Идем дальше.
Теперь занкомиься с понятием "символ". Вы знакомы с этим понятием в узком круге -- буква, цифта или знак препинания. Компиляторы, линковщики и прочиеутилиты рассматривают понятие "символ" как эквивалент имени констатны, имени переменной, имени функции. То есть несколько более расширено.
В нашем предыдущем коде символами являются следующие дефиниции: FCPU, BAUD, delay100ms, UBBRL. Какие-то из символов уйдут при компиляции, какие-то остануться вплоть до elf-файла. Ну, например, FCPU и BAUD скорее всего вы уже не найдете в elf-файле? А вот delay100ms -- он будет отаваться долго. Если вы пишите прогу для компа, а не для микроконтроллера, то этот символ также будет присутствовать и в исполняемом файле, если вы ничего специально не предпримите для его (точнее -- для их) удаления.
Так вот, символ -- это какая-то программная единица с уникальным именем.
До сих пор мы с вам говорили о символах, которые определены в программном коде. Но символы можно также определить (или задать) вне исходных текстов программы. Например, подставлять их в качестве параметра в строку при вызове компилятора:
Код
avr-gcc -mmcu=atmega32 -Wall -Os -DF_CPU=7372800UL -c -o myproga.o myproga.c
Это почти реальная строка для компиляции файла myproga.c в объектный файл myproga.o. Здесь компилятор -- avr-gcc, тип процессора atmega32, ну и так далее.
Обратите внимание на параметр -DF_CPU=7372800UL. Понятно, что эта конструкция определяет тактовую частоту. Но как! Имя "F_CPU" -- это ни что иное как символ. Конструкция "-D" -- это имя параметра. Черточка '-' говорит компилятору, что далее последует имя ключа. (В Виндовсе обычно используется знак '/' а не черточка.) Буква 'D' -- имя ключа, производное от слова DEFINE. И сразу за именем ключа следут имя символа. С непривычки это , конечно, кажетя одиозным! Чужая идеология, чужие понятия, чужие ценности. Но тот, кто постоянно этим пользуется не видят вообще ни каких проблем. Проблема чистов перестройке мышления. Однако, мы отошли от темы!
Так вот. С точки зрения компилятора, ему нет никакой разницы в том, откуда к нему пришел тот или иной символ -- из исходного теста программы или из командной строки. Во время совей работы компилятор составляет таблицы символов. И как в эту втаблицу попадают символы -- дело десятое. Главное чтобы таблица была и была валидной в работе.
Ну и наконец нам остается уточнить, что в работе мы используем Makefile. А это занчит, что в Makefile мы можем задать наши определения, например, вот так:
Код
MCU=atmega32
CC=avr-gcc
COMMON=-mmcu=$(MCU)
## Compile options common for all C compilation units.
CFLAGS=$(COMMON)
CFLAGS+=-Wall -DF_CPU=7372800UL -Os
...
и далее в этом Makefile их использовать для компиляции вот так:
Код
$(CC) $(CFLAGS) -c -o myproga myproga.c
или что тоже самое:
Код
avr-gcc -mmcu=$(MCU) -Wall -DF_CPU=7372800UL -Os -c -o myproga myproga.c
Ну, вроде бы доходчиво объяснил, откуда что берется.
И да! Чуть не забыл. Если вы посмотрите на проекты, в которых используется ARM-ы, то вы увидите, что символы задаются не только в исходниках и Makefile. Символы задаются еще и в ld-файле, который отвечает за сборку проекта. Тут вы найдете такие символы, как адреса начала оперативной памяти, ее размера. начало и размер флешь-памяти. Названия секций (text, data, bss и другие). И многие другие нужные символы.
Это по началу кажется очень сложным. Но когда познакомишься с "механикой", то начинаешь приходить к мысли, что ты реально Бог для своего проекта. Всё, абсолютно всё в твоей власти. И ты четко понимаешь как всё устроено и как на выходе получается код. Всё открыто, всё прзрачно. И самое главное -- что нужно сделать, чтобы внести те или иные изменения.
Ладно. Много напасал. Бодрости духа вам и здоровья! Остальное добудете сами!