Учебный курс AVR. Использование загрузчика (bootloader`a)

12/12/2012 - 20:29

   Введение

   Микроконтроллеры AVR имеют возможность самопрограммирования, то есть могут самостоятельно изменять содержимое своей flash памяти. В практическом плане это означает, что, написав для микроконтроллера специальную программу-загрузчик (так называемый бутлоадер), мы можем обновлять его прошивку, не используя программатор. Причем интерфейс, по которому в микроконтроллер будет передаваться код программы, может быть совершенно произвольным. Обычно для этих целей используется один из аппаратно поддерживаемых интерфейсов, например, SPI, I2C или RS-232. Однако существуют и загрузчики, основанные на программной реализации таких интерфейсов как USB и 1-Wire.
   Для микроконтроллеров AVR существует несметное количество готовых бутлоадеров, и в большинстве случае мы можем спокойно использовать их в своих устройствах, не утруждая себя написанием собственного загрузчика.  В этой статье мы рассмотрим один из таких бутлоадеров, который разработан и свободно распространяется фирмой Chip45, и разберемся как его использовать. 

   Загрузчик (bootloader). Теория

    Память программ микроконтроллеров AVR разделена на две секции – секцию прикладной программы и секцию загрузочной. Загрузчик (или бутлоадер) – это просто программа, которая хранится в одноименной секции и может осуществлять запись/чтение обоих секций памяти микроконтроллера. Эта особенность позволяет загрузчику модифицировать и даже удалять самого себя! То есть совершать своего рода программный суицид.  
   Для того чтобы мы могли воспользоваться удобствами загрузчика, его нужно с помощью программатора записать в память микроконтроллера. Область памяти, в которую будет записываться загрузчик, указывается в конфигурационном файле линкера перед компиляцией исходного кода загрузчика.  Эта тема выходит за рамки данной статьи и здесь мы ее рассматривать не будет. Для нас важно другое, если у нас есть готовый hex файл загрузчика, нам не нужно ни о чем думать, мы просто прошиваем его в микроконтроллер точно так же, как и самую обычную программу!
   Размер секции загрузчика и секции прикладной программы задается  с помощью конфигурационных битов BOOTSZ1, BOOTSZ0. Для микроконтроллера ATmega16 размеры секций памяти в зависимости от значений конфигурационных битов будут выглядеть так. 

 Размер загрузочной области mega16
   Максимально возможный размер загрузочной секции для ATmega16 составляет 1024  16-ти разрядных слова, что соответствует 2 Кб его flash памяти. Если загрузчик не используется, прикладная программа может занимать весь доступный объем flash памяти микроконтроллера.
   Значение конфигурационных битов зависит от требований конкретного загрузчика. Например, для бутлоадера фирмы Chip45 требуется загрузочная секция размером в 1024 слова (2 Кб), но можно написать и более компактный загрузчик. Все зависит от закладываемой в него функциональности и вашего умения кодить.   

   Допустим, мы записали в микроконтроллер бутлоадер, как им воспользоваться? Чтобы загрузчик заработал, его нужно активировать (запустить). Сделать это можно двумя способами:

- переместить вектор сброса в начало загрузочной секции,
-  осуществить переход на начало загрузочной секции.
 
   Реализация первого способа требует установки конфигурационного бита BOOTRST.  Все мы знаем, что после подачи питания или события сброса, микроконтроллер начинает выполнять свою программу с нулевого адреса памяти программ, то есть с вектора сброса. По этому адресу, как правило,  размещается ассемблерная команда безусловного перехода на прикладную программу. Установка бита BOOTRST переносит вектор сброса микроконтроллера AVR на начало его загрузочной секции (например, на адрес 0x1C00, если наш микроконтроллер ATmega16 и оба бита BOOTSZ1, BOOTSZ0 равны нулю), соответственно при старте он сразу начинает выполнять код загрузчика. 
 
Расположение вектора сброса в зависимости от fuse бита
 
   Реализация второго способа подразумевает, что микроконтроллер содержит и загрузчик, и пользовательскую программу, которая будет осуществлять переход в загрузочную область при наступлении какого-нибудь события.  
   Для реализации такого перехода нужно: создать указатель на функцию, присвоить ему адрес начала загрузочной секции и осуществить вызов функции с помощью этого указателя. Например, так:

 
//адрес начала загрузочной секции ATmega16
#define BOOT_SECTION  0x1C00
//объявление указателя на функцию
 void(*pBootloader)(void) ;
 
//если нажата кнопка, запустить загрузчик
if (Button()){
  //инициализация указателя 
   pBootloader = (void(*)())BOOT_SECTION;
   //переход на начало секции загрузчика
    pBootloader ();
}
 
где (void(*)()) – это выражение для приведения типа данных
 
   Когда микроконтроллер переходит в секцию загрузчика, он, если так можно выразиться, “бросает все свои дела”, даже если они не закончены. В некоторых приложениях такое поведение может быть не допустимо (простейший пример – устройство управления нагревательным элементом), поэтому перед запуском загрузчика потребуется привести микроконтроллер или  устройство в какое-то нейтральное положение. Помните про это!
 
   Что происходит, когда загрузчик записал в память микроконтроллера прошивку? Он или запускает прикладную программу сам или ожидает какой-то команды от управляющей программы на компьютере. Это уже зависит от реализации конкретного бутлоадера.   
 
   И последний момент, если вы по привычке зашьете пользовательскую программу в микроконтроллер с помощью программатора, загрузчик будет удален. 

   Бутлоадер фирмы Chip45

   Перейдем к рассмотрению загрузчика фирмы Chip45. В чем его особенность?

1. Наличие готовых прошивок загрузчика под большую номенклатуру AVR микроконтроллеров, а также микроконтроллеров XMEGA. Не нужно компилировать прошивку самому!


2. Простая и удобная графическая оболочка для работы с загрузчиком, а также наличие ее портов под несколько операционных систем (Windows, Linux, Mac OS X).

3. Простой командный интерфейс для работы через терминальные программы.

4. Использование для обмена данными UART модуля, что позволяет загружать прошивку в микроконтроллер по RS-232 или USB, в случае использования USB-UART преобразователя.

5. Поддержка интерфейса RS-485.

6. Возможность чтения/записи EEPROM памяти.

7. Автоматическая установка скорости обмена UART`a с хостом независимо от тактовой частоты микроконтроллера.

8. Дополнительные возможности по активации загрузчика, путем отправки произвольной строки.

9. Требуемый размер загрузочной секции – 1024 слова (2 Kб flash памяти)

Запись загрузчика в микроконтроллер состоит из следующих шагов:

- устанавливаем размер загрузочной секции равной 1024-м словам,
- устанавливаем конфигурационный бит BOOTRST,
- запрещаем деление тактовой частоты, если есть бит CLKDIV8,
- запрещаем работу сторожевого таймера, если он включен битом WDTON,
- выбираем подходящую под наш микроконтроллер прошивку,
- записываем ее в микроконтроллер с помощью любого программатора.

   Основную сложность у новичков здесь может вызвать правильная установка конфигурационных битов. С ними часто происходит путаница, потому что некоторые программаторы воспринимают 1 в конфигурационном бите, как незапрограммированное состояние, 0 – как запрограммированное, а некоторые наоборот. Первый вариант соответствует datasheet`ам микроконтроллеров AVR (смотрите картинку выше).  
   Единственно, могу вас успокоить - неправильная установка этих битов не заблокирует возможность программирования микроконтроллера обычным программатором.
 
Программирование микроконтроллера с помощью загрузчика осуществляется так:
 
- подключаем микроконтроллер к компьютеру по RS-232 или USB, используя USB-UART преобразователь,
- запускаем программу Chip45boot2 GUI (она должна быть установлена),
- устанавливаем нужный COM порт и скорость обмена,
- выбираем hex файл для загрузки в микроконтроллер,
- нажимаем кнопку “Connect to Bootloader”,
- сбрасываем микроконтроллер,
- если в программе загорелся индикатор успешного коннекта, записываем в микроконтроллер прошивку, нажав на кнопку “Program Flash”,
- запускаем приложение, нажав кнопку “Start Application”
 
  Программа Chip45boot2 GUI также позволяет активировать загрузчик путем отправки произвольной строки. Конечно, для этого в микроконтроллере уже должна быть  прошивка, поддерживающая такую возможность. 
   Это может быть удобно, если устройство на микроконтроллере не имеет доступной кнопки сброса, ну, например, оно намертво закрыто в корпусе. 
  Остальную информацию найдете в техническом описании на этот бутлоадер, хотя большую часть я вам рассказал. 

Оболочка для работы с загрузчиком от Chip45
 

Ссылки

скачать загрузчик (bootloader) для AVR