Завантажувач для dsPIC33

Завантажувач (bootloader) — дуже зручний інструмент роботи з мікроконтролерами (далі — МК). Це маленька програма, яка дозволяє МК «самопрограммироваться» (self-programming). Зазвичай, при подачі живлення на МК, управління спочатку отримує завантажувач, які перевірять заздалегідь задані умови (певний стан на ніжці МК, прапор в EEPROM, відповідний файл на SD-карті і т. д.). Якщо умови не виконуються, то управління передається основній програмі. Якщо ж умови виконуються, то завантажувач перемикається в режим програмування, отримуючи дані нової прошивки з зумовлено інтерфейсу. Це дозволяє оновити прошивку МК не вдаючись до паяльнику, програматора або внутрисхемному програмування.

Звичайний алгоритм використання завантажувача для МК, тільки що вийнятого з упаковки:

  1. за допомогою програматора/відладчика прошивається завантажувач
  2. МК монтується в плату
  3. використовуючи завантажувач за заздалегідь визначеним інтерфейсу завантажується основна прошивка
Це цілком прийнятно для дослідних зразків виробів або для дрібносерійного виробництва. А що робити, якщо виробництво багатосерійне? Або збірка проводиться автоматами (а може людьми з функціоналом автоматів) — прошив, впаяв? Тоді розумно прибрати з алгоритму 3го пункт — об'єднати в одній прошивці і основну програму і завантажувач.

У своїй практиці я зіткнувся з досить моторошним методом отримання такої прошивки — в HEX-файл основний прошивки просто дописывался HEX-файл з кодом завантажувача. Звичайно. такий підхід має право бути — як не крути, але підсумкові «прошивки імені ін. Франкенштейна» працювали як треба. Але почуття, що для вирішення цього завдання повинні бути більш коректні методи, мене не залишало.

Коли Я пошукав рішення в Інтернеті, то був неприємно здивований, що простого і зрозумілого опису рішення немає. Власне, саме це спонукало мене написати публікацію, що описує моє рішення цієї ситуації. Можливо моє бачення вирішення цієї проблеми відрізняється від максимально правильного, але воно набагато логічніше, ніж зшивання HEX-файлів.

Перш ніж перейти до самої теми публікації, хочу навести список спрощень та інструментів, які були використані:

  • MPLAB IDE v8.85 (так, досить застаріла IDE)
  • Microchip C30 Toolsuite v3.12
  • об'єктні файли у форматі COFF (тобто за замовчуванням для цього toolchain-a)
  • розташування завантажувача і основної програми статичні
  • завантажувач розташовується з адреси 0х0400
  • основна програма розташовується з адреси 0х2000
  • пам'ять за адресами з 0х0200 за 0х0400 — невживана
І найголовніше — конкретних початкового завантажувача в цей публікації не буде.

Компонування завантажувача в основний проект
Просто скомпілювати...
Почнемо з самого простого випадку. Добрий Дідусь Мороз надіслав Вам на Новий Рік готовий завантажувач. Причому він вже попрацював на славу і скомпілював і скомпонував його для Вас. Отже, у Вас в руках (на флешці/в мережі/на жорсткому диску) є файлик – UltraBoot3000.blob. Далі алгоритм дуже простий – просто додай його до себе в проект.

Стосовно MPLAB IDE його треба додати в категорію «Object Files». На жаль, за замовчуванням у цю категорію можна додати тільки файли з розширенням «o». Зазначу також, що файли з розширенням «o» виходять так само в процесі компіляції Вашої програми. Щоб випадково не переплутати і не забути про файл завантажувача, рекомендую тримати його з іншим розширенням, наприклад blob – binary linked object. Щоб IDE поклало файл blob в категорію «Object Files», цієї категорії потрібно скоригувати настройки фільтрів. Тиснемо правою кнопкою миші на цій категорії і вибираємо пункт «Filter...». У вікні В полі через крапку з комою дописуємо необхідний шаблон фільтра. У нашому випадку в полі повинно бути в підсумку наступне опис фільтрів:

*.o;*.blob
 

Після налаштування фільтрів можна додати файл завантажувача в проект.

Запускаємо процес компи… НЕМАЄ! СТОП!

Щоб коректно зібрати прошивку з нашим завантажувачем, потрібен правильний скрипт конструктора. Звичайно, якщо Дідусь Мороз був настільки добрий, що і цей скрипт Вам прислав, то просто додаємо його собі в проект (MPLAB IDE підтримує файли з розширенням «gld»), запускаємо процес складання проекту і на виході отримуємо коректний файл прошивки з вже вбудованим кодом завантажувача.

Але що робити, якщо Дідусь забув про це скрипт або може бути саме Ви і є тим, хто зробив цей завантажувач і Вам треба вмонтувати його в свій/чужий проект? Читаємо далі…

Підготовка скрипта конструктора
Власне не варто писати скрипт з нуля. Достатньо трохи переробити скрипт, який встановлюється в комплекті з компілятором. Лежить цей скрипт в папці «${ToolChainPath}\support\dsPIC33F\gld\». Примітка: тут і далі ${ToolChainPath} – це шлях, куди був встановлений компілятор С30, за замовчуванням це – «c:\Program Files\Microchip\MPLAB C30\». Скопіюємо звідти скрипт за замовчуванням для нашого пристрою, наприклад для МК dsPIC33FJ128GP802 це буде файл «p33FJ128GP802.gld».

Першим ділом треба вписати два символи, які описують початок області завантажувача і основної програми. Наприклад, так:

_Booter = 0x000400;
 
_mainFW = 0x002000;
 

Далі в структурі MEMORY {...} у полі program вказати початкову позицію (origin) і довжину (length), відповідні початку завантажувача і розміром flash-пам'яті мінус початок завантажувача. Приблизно так:

program (xr) : ORIGIN = 0x400,LENGTH = (0x15800 - 0x400)
 

Наступним кроком буде коригування вектора скидання. У структурі SECTIONS {...} знайдемо опис «Reset Instruction». Необхідно щоб вона виглядала наступним чином:

.reset :
 
{
 
SHORT(ABSOLUTE(_Booter));
 
SHORT(0x04);
 
SHORT((ABSOLUTE(_Booter) >> 16) & 0x7F);
 
SHORT(0);
 
} >reset
 

Залишилося тільки додати опис зони завантажувача. Зона описується в структурі SECTIONS {...}. Це опис необхідно вставити перед описом зони «.text». Опис наступне:

.boot _Booter : 
 
{
 
*(.booter);
 
. = _mainFW - _Booter;
 
} >program = 0xFFFF
 

Отже, скрипт готовий.

Створення завантажувача
Зробити завантажувач з програми
Перше, що хотілося б відзначити: завантажувач не повинен бути самостійною програмою. Звичайно, в процесі налагодження завантажувача його можна реалізувати як самостійну програму. Але як тільки Ви плануєте його вмонтувати в іншу програму його необхідно спеціально підготувати.

Отже, чого позбавляється програма, перетворюючись в завантажувач:

  1. Опис конфігураційних біт
  2. Векторів переривань
  3. Вектора скидання
Крім цього, неможливо коректно вбудувати константи завантажувача, збережені у флеш-пам'яті, код основної програми. Тому від них теж доведеться відмовитися. Примітка: насправді спосіб є, але він настільки нетривіальне, що для масового використання простіше відмовити від констант у завантажувачі.

Доопрацювання вихідних текстів
Доробка нескладна. Прибираємо всі макроси, що описують конфігураційні біти. Виключаємо використання глобальних констант.

Налаштування проекту
Так само необхідно перевірити і, при необхідності, скорегувати параметри проекту. Всі зміни – у вкладці «MPLAB LINK30», категорія «General». Встановити чек-бокси: don't pack data template; don't create hanldes; don't create default ISR; remove unused sections.

Доопрацювання скрипта конструктора
Так само як і для основної програми з завантажувачем скрипт буде відмінним від скрипта за замовчуванням. Отже, беремо скрипт за замовчуванням і вносимо наступні зміни.

Структуру MEMORY {...} зменшуємо до двох позицій: data і program. Причому початок і довжина program відповідають початку і довжині області завантажувача:

{
 
data (a!xr) : ORIGIN = 0x800, LENGTH = 0x4000
 
program (xr) : ORIGIN = 0x400, LENGTH = 0x1C00
 
}
 

Видаляємо повністю опис «Reset Instruction» в структурі SECTIONS {...}. У цій же структурі видаляємо опис «Configuration Words». Повністю видаляємо структуру SECTIONS {...}, яка описує вектора переривань (мітка «Section Map for Interrupt Vector Tables»).

У структурі SECTIONS {...} допрацьовуємо опис зони «.text», замінивши назву зони «.booter» і привівши її до наступного вигляду:

.booter 0x400 :
 
{
 
*(.init);
 
*(.user_init);
 
*(.handle);
 
*(.libc) *(.libm) *(.libdsp); /* keep together in this order */
 
*(.lib*);
 
*(.dinit);
 
*(.text);
 
} >program
 

Природно, отриманий скрипт треба додати в проект.

Постобробка вихідного файлу
Після здійснення попередніх дій можна запустити процес компіляції. У висновку процесу складання (для MPLAB IDE це буде у вікні Output, вкладка Build) можна побачити результат компонування. Наприклад, так:

Program Memory [Origin = 0x400, Length = 0x1c00]
 

 
section address length (PC units) length (bytes) (dec)
 
------- ------- ----------------- --------------------
 
.booter 0x400 0x7d0 0xbb8 (3000)
 

 
Total program memory used (bytes): 0xbb8 (3000) 27%
 

 
Data Memory [Origin = 0x800, Length = 0x4000]
 

 
section address alignment gaps total length (dec)
 
------- ------- -------------- -------------------
 
.nbss 0x800 0 0xa2c (2604)
 
bootdata 0x47c0 0 0x40 (64)
 

 
Total data memory used (bytes): 0xa6c (2668) 16%
 

Якщо в program memory більше однієї секції – то скоріше всього ви не до кінця виконали дії описані вище. Якщо там саме одна секція з назвою «.booter» — то все зроблено правильно.

Також треба звернути увагу на кількість секцій data memory.

Тепер треба виконати обробку вихідного файлу. Постобробка проводитися з файлом з розширенням «cof». Відкриваємо " командний рядок в папці з цим файлом. Припустимо файл має ім'я ultraboot.cof, тоді виконаємо команду:

"${ToolChainPath}\bin\pic30-strip.exe" -s --remove-section=.nbss --remove-section=bootdata -o ultraboot.blob ultraboot.cof

Не забуваємо ${ToolChainPath} замінювати на реальний шлях. Кількість опцій «--remove-section=...» повинно відповідати кількість секцій data memory (з виведення результату роботи конструктора).

Далі треба провести фінальну перевірку отриманого бінарного файлу з завантажувачем. Команда:

"${ToolChainPath}\bin\pic30-objdump.exe" -ht ultraboot.blob

Висновок буде приблизно таким:

ultraboot.blob: file format coff-pic30
 

 
Sections:
 
Idx Name Size VMA LMA File off Algn
 
0 .booter 000007d0 00000400 00000400 00000058 2**1
 
CONTENTS, ALLOC, LOAD, CODE
 
SYMBOL TABLE:
 
no symbols
 

Якщо ви побачите, що секцій рівно одна — з назвою «.booter» і символьної таблиці немає символів, то можна вважати, що все зроблено коректно.

І в кінці посилання на приклади файлів для лінкера:

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.