Неточності в технічному описі і особливості використання Bootloader через порт USART
Довелося робити програму для запису через Bootloader в FLASH-пам’ять контролерів із сімейства STM32L…, або STM32F…., словом, STM32….
Перші враження від цих контролерів: надзвичайно складно, і надзвичайно чудово.
Чому складно ? Контролери мають до непристойності багато можливостей, але опис тих чи інших функцій робиться компанією STMICROELECTRONICS по можливості так, щоб програмісти не чіпали ці контролери, і зайнялись чимось іншим.
А чому чудово ? Та тому, що швидкість роботи контролера така, що згадувати про значно повільніші AVR вже не хочеться.
Програмуючи електроніку з надписом STM32…(далі не важливо), регулярно доводиться наштовхуватись на невідповідність того, що написано в тій чи іншій сервісній інструкції, і суворою реальністю. Назбиравши деякий список “як написано” і “як насправді”, вирішив описати все це в невеличкій коректуючій статті.
Коректувати будемо технічний опис (даташіт) функцій стартового загрузчика (bootloader, “бутлодер”). Цей загрузчик забезпечує запис необхідної інформації в пам’ять контролера, тобто програмування контролера, а також прочитування інформації з пам’яті і виконання ще деяких необхідних сервісних функцій.
Технічний опис називається “AN3155 AN2606 Application note”, і головна тема опису – “USART protocol used in the STM32 bootloader”, тобто протокол інтерфейса USART загрузчика контролера STM32.
Опис охоплює такі групи контролерів:
STM32L0, STM32L1, STM32F0, STM32F1,
STM32F2, STM32F3. STM32F4
Англійський варіант опису лежить на сайті www.st.com
Нагадую, нас цікавлять неточності цього опису.
Отже, у нас є контролер, на нього подано живлення, наша задача – запрограмувати контролер з допомогою спеціалізованої, нами розробленої програми. Навіщо робити свою програму, коли є стандартні ? Варіантів багато:
– можливо, потрібен віддалений доступ, який важко організувати, використовуючи стандартну програму для роботи з бутлодером.
– можливо, потрібне спеціалізоване “засекречування” прошивки контролера.
– можливо, замовник хоче програмувати якимись своїми програмними засобами, і стандартний програматор не годиться.
Так чи інакше, треба зробити свою програму для роботи з бутлодером. Я звик називати “стартовий загрузчик”, але доведеться називати тупим жаргоном “бутлодер”.
Як “викликати на себе” бутлодер з мікроконтролера ? Це просто. В сімействі контролерів, які ми розглядаємо, є інформаційні входи BOOT0 і BOOT1.
Через який порт зайкраще працювати з бутлодером ?
Залежно від модифікації, бутлодер працює з портами USART, або з портами USART і DFU, або USART і CAN, або USART і SPI, далі можна не продовжувати. Зрозуміло, що найпростіше запрограмувати контролер через інтерфейс USART, ми вибираємо найбільш простий шлях.
Вхід BOOT1 надійно підключений до логічного “0“, тобто через резистор – на “землю”. Вхід BOOT0 – також через резистор на “землю”, але ми подамо на нього логічну “1“, коли почнемо програмування контролера.
Для більшості контролерів цієї серії є проста закономірність:
– На вході BOOT0 логічний “0“. При подачі живлення контролер культурно стартує з FLASH-пам’яті.
– На вході BOOT0 логічна “1“, на вході BOOT1 логічний “0“. При подачі живлення контролер стартує зі своєї, недоступної нам для зіпсування системної пам’яті.
– на входах BOOT0 і BOOT1 логічна “1“. При подачі живлення контролер стартує з тої програми, яка записана в оперативній пам’яті SRAM. При скиданні живлення ця програма руйнується.
Програма в FLASH-пам’ять контролера записується тим отладчиком, який у нас є під руками, наприклад, це дешевий китайський ST-LINK. Дешевий китайський ST-LINK вміє створювати нам проблеми.
– якщо робоча частота нашого контролера зависока, ST-LINK може не бачити контролера взагалі і не пробувати щось кудись записати. Або так-сяк записує, але отладочний режим, із контрольними зупинками та іншими корисними функціями, практично не працює.
– якщо при ввімкненні живлення ваша програма переводить контролер в сплячий режим, цей контролер також може стати “невидимим” для ST-LINKа.
– не сумніваюсь, є ще немало особливостей вашої програми, які можуть, як кажуть на форумах, “закирпичити” ваш контролер, перетворити контролер на цеглину, в яку ніякий отладчик нічого не запише.
А вихід є ! Досить лише на вхід BOOT0 подати логічну “1“, і в контролер знову можна писати потрібну програму. Звісно, потім треба не забути на вхід BOOT0 подати логічний “0“, бо інакше контролер “не почне працювати” при простій подачі живлення, бо він переходить на виконання програми із своєї системнорї пам’яті. Зараз ми з цією системною програмою почнемо працювати. Отже !
1. На вхід BOOT0 подаємо логічну “1“,
2. Формуємо одиночний імпульсний сигнал “Reset”, короткий “0” і далі логічна “1“.
Неточність в описі: насправді сигнал “Reset” не може бути нескінченно коротким, приходиться витримувати хоча б 10 мілісекунд (10 мс). Формую для підстраховки 50 мс, часу у мене багато. Тепер, згідно опису, на інтерфейсний вхід TX01 можна подавати байт 0x7F згідно протоколу послідовного інтерфейса USART.
Неточність в описі: після Reset доведеться почекати не менше, ніж 0.1 секунди. Адже електронщики підключили до входу Reset лише конденсатор, а скидувати Reset в “0” рекомендується “відкритим колектором”. Значить, чекаємо, доки на вході Reset надійно встановиться логічна “1”.
Отже, можна подавати байт 0x7F. Розглянемо детально.
В протоколі USART спочатку “нулем” формується стартовий біт, потім побітно йдуть 8 біт нашого байта, починаючи з молодшого біта і закінчуючи старшим, Потім йде “парний біт”. В деяких протоколах він може бути “непарним” або відсутнім. Для бутлодера він має бути парним.
В кінці йдуть два стоп-біти, вони йдуть логічною “одиницею”.
Швидкість передачі біт вибираємо стандартну, починаючи з 1200 бод, і закінчуючи 115200 бод. При наладці програми програматора можна наугад вибрати 19200 бод.
Неточність в описі: написано, що бутлодер одержить байт 0x7F і негайно віддасть байт 0x79 (така відповідь називається ACK), показуючи, що він готовий до роботи. В реальності бутлодер деяких контролерів може нічим не відповісти. Доводиться, почекавши 0.1 секунди, знову подавати байт 0x7F і так само приблизно 0.1 секунди чекати на відповідь. Довелось в моїй програмі до 10 раз повторювати цю процедуру, щоб гарантовано витрясти відповіль з бутловера. Але спрацьовує не після 10 раз, а після 2-3 раз. А в деяких контролерах відповідає зразу, з першого запиту.
Бутлодер вже в робочому стані. Далі буде краще. Розглядуємо функції (команди) бутлодера.
Get command
Ніяких претензій не маю, працює нормально, і згідно з описом.
Get version, Get ID command – працює нормально. Потрібність цих функцій відносна, ви й так добре знаєте, який контролер хочете запрограмувати.
Read Memory command
Дуже потрібна команда. Наштовхуємось на необхідність самим формувати контрольну суму. Контрольна сума завжди є такою, щоб при “додаванні по модулю 2” байтів інформаційного блока і контрольної суми ми одержували число 0xFF.
“Додавання по модулю 2” – це одна з назв додавання XOR, в компіляторі “C” це додавання позначається значком “^“.
Наприклад, C=A ^ B;
Отже, команда Read Memory. Передаємо байт 0x11 і його контрольну суму 0xEE, чекаємо відповіль ACK, це байт 0x79.
Передаємо 4-байтну адресу в пам’яті контролера, починаючи зі старшого байта, і контрольну суму. Чекаємо на відповідь ACK.
Передаємо одним байтом кількість байт, які ми хочемо прочитати, і контрольну суму цієї кількості.
Наприклад, це байти 0x10 і 0xEF. Кількість = 16 = 0x10, а контрольна сума = 0xEF.
Чекаємо на ACK.
Далі ми одержимо байти з пам’яті контролера в необхідній кількості.
Неточність в описі: ні, це ще не все. Незважаючи на опис, далі ми одержимо байт ACK. Якщо ми його не прочитаємо, він нам залізе в буфер (якщо читання по протоколу USART у нас буфероване) і зіпсує нам інформаційну картину.
GO command – ця команда успішно виконується, її потрібність незначна.
Write Memory command
Це головна команда з усіх, що нам потрібні.
Передаємо 0x31 і контрольну суму 0xCE. Чекаємо ACK.
Передаємо 4 байти адреси пам’яті контролера і контрольну суму. Адреса – зі старшого байта до молодшого.
Чекаємо ACK.
Далі уважно.
1. Кількість байт, які ми записуємо, завжди повинна бути кратна 4. Ми можемо записати 20 байт, але не можемо записати 19 або 21.
2. Вибираємо потрібну нам кількість байт (це число кратне 4), віднімаємо від нього 1, і результат передаємо одним байтом в контролер.
3. Передаємо необхідні байти для запису.
4. Передаємо контрольну суму. В контрольну суму входить “кількість байт -1” і передані інформаційні байти.
5. Чекаємо ACK.
Erase Memory command і Extended Erase Memory command
Команди хороші, але працюють погано.
1. Для різних контролерів різні розміри сторінок FLASH-пам’яті, які підлягають стиранню.
2. Для деяких контролерів немає стирання по сторінках, там стирання по секторах.
3. Кінцева відповіль ACK приходить не відразу, а лише після витирання вказаних сторінок.
4. Деякі контролери підтримують команду Erase Memory command, інші підтримують команду Extended Erase Memory command. Немає контролерів, які підтримують обидві групи команд.
5. В деяких контролерах після витирання сторінки діалог припиняється.
А як продовжувати роботу ?
Тепер доведеться застосовувати такий ланцюжок:
“чекання 50 мс” – “Reset” – “чекання 50 мс” – “передача байта 0x7F” – “отримання байта 0x79” (а в деяких контролерах ці дві останні дії доводиться виконувати кілька раз, це було описано на початку статті) і далі бутлодер знову готовий до роботи. Такий ланцюжок можна назвати “повторний запуск бутлодера”, нам цю назву ще доведеться згадувати.
Важливо ! В повторному запуску бутлодера категорично потрібно на початку витримувати паузу в кілька десятків мілісекунд. Саме тому така пауза вказана в ланцюжку повторного запуску бутлодера. Зрозуміло, що ця пауза може бути трохи коротшою.
Write Protect command і Write Unprotect command – працюють нормально.
Readout Protect command – працює нормально.
Увага ! Після виконання цієї команди – обов’язковий повторний запуск бутлодера.
Readout Unprotect command – працює нормально. Виконується довго, кілька секунд.
Увага ! Після виконання цієї команди – обов’язковий повторний запуск бутлодера.
Рекомендація виробників. Хто не хоче зайвих складнощів, той не користується очисткою FLASH-пам’яті контролера методом Erase Memory command або Extended Erase Memory. Рекомендують спочатку захистити FLASH-пам’ять від зчитування захистом першого рівня (це виконується командою Readout Protect command) а потім зняти захист (Readout Unprotect command). Після таких дій FLASH-пам’ять чиста-чиста. Така послідовність є універсальною, а тому зручною.
——————————————————————————————————–
Чи не пропустив я що-небудь ? Для тих, хто хоче щось додати, завжди є коментарі.
——————————————————————————————————–
Весь список статей нашого сайту, корисних для програмістів, знаходиться ось тут
Вітаю друже. Маю складнощі з чек сум
“31 CE 08 00 00 00 08 FF 00 40 02 20 75 0D 00 08 3D 0D 00 08 43 0D 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 49 0D 00 08 00 00 00 00 00 00 00 00 53 0D 00 08 5D 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 C5 0D 00 08 10 B5 06 4C 23 78 00 2B 07 D1 05 4B 00 2B 02 D0 04 48 00 E0 00 BF 01 23 23 70 10 BD 10 00 00 20 00 00 00 00 F4 37 00 08 04 4B 10 B5 00 2B 03 D0 03 49 04 48 00 E0 00 BF 10 BD C0 46 00 00 00 00 14 00 00 20 8F”
31 CE – Write Memory command
08 00 00 00 -адреса сторінки
08 – (чек сум 8) “08 00 00 00”
FF-Довжина
У кінці маємо 8F але як її взяти не розумію.
Розумію що це усі данні та далі вираховати не можу.
Підскажіть будласка як далі.
Та я би підказав, але є неясності.
Бачу, що ви працюєте із якимось контролером сімейства SIM32……
А навіщо самому вираховувати контрольну суму ?
Я, наприклад, користуюсь отладчиком IAR, тут і створення самої програми, і наладка програми безпосередньо в контролері. Є й інші отладочні системи. Для апаратної взаємодії з контролером користуюсь ST-LINK V2, він простий і дешевий.
І будь-які записи в пам’ять чи зчитування з пам’яті вони роблять самі, не видавлюючи з мене ніяких контрольних сум.
Попробуйте уточнити своє запитання.
Але якщо ви запитуєте про BootLoader, то команда запису в пам’ять – саме така, як написано в статті, мною перевірено, і контрольна сума саме ЦІЄЇ КОМАНДИ формується саме так, як написано в статті.