UM0560: загрузчик STM8, руководство пользователя |
![]() |
Добавил(а) microsin | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Этот документ (перевод руководства [1]) описывает функции и работу встроенного в микроконтроллер (MCU) STM8 загрузчика STSW-STM8068 (bootloader). Этот код находится в постоянной системной памяти MCU (ROM) и позволяет записать области встроенной памяти, включая память программ Flash, EEPROM данных и RAM. Записываемые данные передаются в MCU через набор стандартных последовательных интерфейсов LINUART/UART/USART, SPI и CAN. Код загрузчика почти одинаковый для всех версий STM8. Однако поддержка тех или иных интерфейсов в зависимости от модели MCU может меняться (например, для 128-килобайтных устройств SPI не поддерживается). Следует отметить, что альтернативным решением для внутрисхемного программирования может также служить интерфейс отладчика SWIM, который осуществляет обмен данными только по одному проводу [3]. После сброса загрузчик проверяет, является ли память программ чистой, или установлен ли определенный байт опций, позволяющий изменять код. Если условия запуска загрузчика не выполняются, то загрузчик запускает код приложения пользователя, иначе загрузчик берет управление на себя и ждет загрузки программы. Когда загрузчик активируется, выполняются следующие основные задачи: • Опрашиваются все поддерживаемые последовательные интерфейсы, чтобы определить, какой интерфейс будет использоваться для загрузки (набор поддерживаемых интерфейсов зависит от модели MCU, см. таблицу 1). В каждом MCU STM8 встроен специфичный код загрузчика, который является общим для целой группы устройств STM8. Соответствие между группами STM8 и моделями STM8 приведено в таблице 1. Все упомянутые группы используются в описании этого руководства. Таблица 1. Группы STM8, поддерживающих загрузчик.
В таблице 2 приведен список устройств STM8 без встроенного загрузчика (внутри кристалла MCU нет ROM bootloader). При использовании этих устройств пользователь должен написать свой собственный загрузчик и сохранить его в области программ UBC program area (см. руководства по сериям STM8S, STM8AF, STM8L, STM8AL и STM8T для получения информации об области памяти UBC). Таблица 2. Группы STM8 без поддержки загрузчика.
[Активация загрузчика] Аппаратный вектор сброса STM8 находится в начале boot ROM (0x006000), в то время как другие вектора прерываний находятся в памяти Flash, начиная с адреса 0x008004. MCU запускает boot ROM (делает безусловный переход в область boot ROM), и после проверки ячеек памяти по определенным адресам (см. далее таблицу 4 "Первоначальные проверки загрузчика"), будет либо активирован загрузчик, либо будет запущен код пользователя, определенный вектором сброса (0x008000). Алгоритм активации загрузчика описан на рис. 1. В предыдущих версиях загрузчика производился возврат в состояние "wait for SYNCH" ("ожидание синхронизации", см. пунктирную линию перехода на рис. 1), когда тест на чистоту памяти Flash ("Flash virgin") был положительный. В более новых версиях это было заменено на программным (software reset, SW reset) сбросом, чтобы предотвратить вход firmware пользователя в бесконечный цикл (например, из-за электромагнитных помех). Эта модификация загрузчика в таблице 15 называется "Защита от блокировки EMC". В таблице 3 перечислены версии загрузчика, в которых пунктирная линия заменена на SW reset. Номер версии загрузчика вычитывается командой Get (см. далее описание команды Get в соответствующей врезке). Версия загрузчика представлена двумя цифрами BCD (с десятичной точкой между двумя цифрами), закодированными в одном байте, который выдается как результат команды Get. Например, байт версии 0x21 обозначает bootloader version 2.1. Таблица 3. Версии загрузчика, для которых верен алгоритм активации на рис. 1.
Рис. 1. Алгоритм активации загрузчика. Примечания: (1) См. далее описание алгоритма загрузчика, где объясняются места алгоритма от 1 до 8. [Алгоритм загрузчика] Здесь приведено описание шагов алгоритма загрузчика на рис. 1: 1. Запрещаются все источники прерываний. 2. MCU может запустить процесс загрузчика с помощью проверок, показанных в таблице 4 - в соответствии с содержимым первой ячейки памяти программ Flash (0x008000) и байт опций, разрешающих работу загрузчика ("bootloader enable" option bytes). MCU проверяет следующие условия запуска загрузчика (этот процесс проверки суммарно перечислен в таблице 4): Условие 1: MCU проверяет, пуста ли память устройства путем анализа содержимого по адресу 0x008000 (вектор сброса). Если байт по этому адресу не равен 0x82 или 0xAC, то определяется, что устройство чистое, и загрузчик остается в активном состоянии и ждет команд от хоста без таймаутов. Условие 2: MCU проверяет, установлены ли байты опций (2 байта) для разрешения работы загрузчика, или нет. Загрузчик разрешается значением 0x55AA, и запрещается для всех других значений (где размещаются эти байты в памяти, см. даташит на используемый MCU). Если в этих байтах опций 0x55AA, то загрузчик остается активным и ждет команд от хоста, пока не истечет таймаут в 1 секунду. Если в течение этого времени хост не передал команду, то загрузчик делает прыжок по вектору приложения пользователя (jump 0x008000). Условие 3: если байты опций запретили загрузчик (там находится значение, отличающееся от 0x55AA), то загрузчик делает прыжок по вектору приложения пользователя (jump 0x008000). 3. Когда защита от чтения (ROP) активна, то чтение памяти программ Flash запрещено. В этом случае загрузчик останавливается и запускается программа пользователя. Если ROP неактивна, то загрузчик продолжает свое выполнение (см. "Приложение A. Как обновить MCU, у которого активна защита ROP"). 4. Периферийное устройство CAN можно использовать только если присутствует определенная тактовая частота, заданная снаружи (8 МГц, 16 МГц или 24 МГц). CAN инициализируется на скорости 125 кбит/сек. Интерфейсам UART и SPI не требуется наличие внешнего тактирования. Нужно подождать 6 мс, чтобы стала стабильной частота кварцевого генератора HSE. 5. Запускается внутренний высокоскоростной генератор RC (HSI) на частоте 16 МГц, и инициализируются ножки приемника UART в режиме входа с верхними подтягивающими резисторами (pull-up) путем настройки регистров GPIO. SPI инициируется в подчиненном режиме (slave mode). Затем происходит ожидание 4 мс, чтобы застабилизировались уровни ножках интерфейсов. Рекомендуется, чтобы хост подождал 10 мс от момента сброса MCU перед отправкой байта/сообщения SYNCH. Это время требуется для инициализации загрузчика. 6. Опрашиваются интерфейсы: все периферийные устройства проверяются загрузчиком в ожидании байта/сообщения синхронизации (SYNCH = 0x7F) в течение таймаута в 1 секунду. Если истек таймаут и память программ Flash чистая, то загрузчик остается активным, в бесконечном цикле ожидая поступления команд от хоста через программный сброс. Если после истечения таймаута память программ Flash не чистая, то загрузчик восстанавливает значения регистров в состоянием по умолчанию, и делает прыжок на вектор сброса (находится по адресу 0x008000). Для версий загрузчика, перечисленных в таблице 3, SW reset генерируется после истечения таймаута в том случае, если память программ пустая (потому что безопаснее оставаться в бесконечном цикле, если присутствует аппаратная ошибка микросхемы). Примечание: при ошибке синхронизации (загрузчик принял байт/сообщение, отличающийся от SYNCH = 0x7F), в соответствии с периферийным устройством можно различать 2 разные ситуации. В случае UART необходим сброс MCU перед тем, как может произойти повторная синхронизация (см. "Приложение E. Ограничения загрузчика UART"). В случае CAN или SPI может быть продолжен опрос интерфейсов, пока не произойдет синхронизация или не истечет таймаут. 7. Если UART-ы приняли сообщение синхронизации, то загрузчик по нему автоматически определит скорость интерфейса, инициализирует UART и перейдет к шагу 8. Если сообщение синхронизации поступило через CAN или SPI, то загрузчик сразу переходит к шагу 8. Примечание: как только один из доступных интерфейсов принял сообщение синхронизации, все другие интерфейсы запрещаются. 8. Ожидание команд: команды проверяются и выполняются в бесконечном цикле. Чтобы выйти из загрузчика, хост должен послать команду GO. После получения команды GO загрузчик удаляет подпрограммы EM и WM из RAM и делает прыжок на адрес, выбранный хостом. Примечание: чтобы можно было записать/стереть данные во Flash и EEPROM, хост должен сначала записать в RAM специальные подпрограммы для записи и стирания. Эти подпрограммы (файлы на языке ассемблера *.s19) предоставляются вместе с загрузчиком. Хост должен выгрузить эти подпрограммы по адресу 0x0000A0. См. далее секцию "Подпрограммы erase/write в памяти RAM". Таблица 4. Первоначальные проверки загрузчика.
Примечания: (1) См. даташит на используемый MCU для места размещения [BL_OPT] байта опций на карте памяти. [Настройки периферийных устройств] В этой секции описываются аппаратные настройки коммуникационных интерфейсов STM8: • UARTs/LINUART Примечание: во время загрузки (когда загрузчик по процедуре синхронизации определил интерфейс и начал работу с ним) используется только один коммуникационный интерфейс, все остальные запрещаются. Таблица 5. Последовательные интерфейсы, связанные с MCU STM8(1).
Примечание (1): таблица выше отражает только текущие версии загрузчиков и состояния устройств. USART/UART. Это периферийное устройство поддерживает последовательный асинхронный обмен. Настройки USART/UART: • Кадр данных: 1 старт-бит, 8 бит данных, 1 бит четности настроен н четность данных, 1 стоп-бит. Чтобы работало автоматическое определение скорости, на плате приложения должна обеспечиваться стабильность сигнала RxD (загрузчик разрешает внутренний pull-up на ножке RxD). Настройки выводов: • Когда загрузчик ожидает байта синхронизации (SYNCH = 0x7F), ножки RxD настраиваются в режим ввода с верхним подтягивающим резистором (pull-up). LINUART/UART в режиме "Reply". Настройки: • Кадр данных: 1 старт-бит, 8 бит данных, без бита четности, 1 стоп-бит. Чтобы работало автоматическое определение скорости, на плате приложения должна обеспечиваться стабильность сигнала RxD (загрузчик разрешает внутренний pull-up на ножке RxD). Режим Reply. Хост должен отвечать на все байты, которые посланы из загрузчика. Если сигналы TxD и RxD используют один и тот же физический вывод (например, обмен 1-wire), то ответы от хоста не обязательны, поскольку выводы RxD и TxD совпадают. Настройки выводов: • Когда загрузчик ожидает байта синхронизации (SYNCH = 0x7F), ножки RxD настраиваются в режим ввода с верхним подтягивающим резистором (pull-up). SPI. Настройки для SPI следующие: • 8 бит данных, MSB идет первым. Перед отправкой байта хост должен выдержать задержку 6 мкс. Периферийное устройство SPI доступно через выводы SPI_SCK, SPI_MOSI и SPI_MISO со следующими настройками: • Когда загрузчик ждет байта синхронизации (SYNCH = 0x7F) ножки SPI_MISO настроены в режиме двухтактного выхода (push-pull). CAN. Чтобы адресовать устройства, подключенные к одной и той же шине, протокол CAN предоставляет в своем кадре поле стандартного идентификатора (Standard ID 11 бит) и опциональное поле расширенного идентификатора (extended ID 18 бит). Рис. 2 показывает кадр CAN, который использует только стандартный идентификатор. Рис. 2. Фрейм CAN. Настройки CAN следующие: • Идентификатор Standard (не Extended). По умолчанию установлена скорость 125 килобит/сек. Эта скорость может быть изменена во время работы загрузчика командой speed, чем может быть достигнута скорость до 1 Mbit/сек. Настройки передачи (от STM8 к хосту): • Tx mailbox0: разрешен. Настройки приема (от хоста к STM8): • Байт синхронизации 0x7F находится в ID RX, а не в поле данных пакета. Приходящие сообщения могут содержать от 1 до 8 байт данных. Периферийное устройство CAN доступно через ножки CAN_TX и CAN_RX, со следующими настройками: • Когда загрузчик ждет байта синхронизации в идентификаторе фрейма CAN (SYNCH = 0x7F), ножка CAN_TX настроена в режиме двухтактного выхода (push-pull). [Команды загрузчика] Команды, поддерживаемые загрузчиком, перечислены в таблице 6. Таблица 6. Команды загрузчика.
Таблица 7. Коды загрузчика.
Когда загрузчик принимает команды через UART, CAN или SPI, общий протокол следующий: 1. Загрузчик посылает байт ACK (0x79) хосту и ждет адрес адрес и байт контрольной суммы, которые проверяются при получении. 2. Когда адрес правильный и контрольная сумма в порядке, загрузчик посылает байт ACK (0x79), иначе посылает байт NACK (0x1F) и обрывает выполнение команды. Загрузчик ждет определенное количество передаваемых байт (N байт) и байт контрольной суммы. – Если контрольная сумма в порядке, то загрузчик выполняет команду, начиная с принятого адреса. Протоколы загрузчика через UART и SPI идентичен внутри MCU, но отличаются со стороны хоста. Нужен байт токена, когда через SPI отправляется каждый байт (см. рисунки 5, 11, 17, 23 и 31). Протокол загрузчика CAN отличается от всех других протоколов. Ниже во врезках описываются команды загрузчика для разных протоколов. Команда Get позволяет хосту получить версию загрузчика и поддерживаемые им команды. Когда загрузчик принимает команду Get, он передаст хосту свою версию и коды поддерживаемых команд. [USART/LINUART/UART1/UART2/UART3] Рис. 3. Команда Get через USART/LINUART/UART1/UART2/UART3 на стороне хоста. Хост отправляет байты следующим образом. Байт 1: 0x00 - Command ID. Рис. 4. Команда Get USART/LINUART/UART1/UART2/UART3 на стороне MCU. STM8 отправляет байты следующим образом. Байт 1: ACK (после того, как хост отправил команду). [SPI] Рис. 5. Команда Get через SPI на стороне хоста. Хост отправляет байты следующим образом. Байт 1: 0x00 - Command ID. Рис. 6. Команда Get через SPI - на стороне MCU. STM8 отправляет байты следующим образом. Байт 1: ACK. [CAN] Рис. 7. Команда Get через CAN на стороне хоста. Хост посылает сообщения следующим образом. Сообщение команды: Std ID = 0x00, код длины данных (DLC) = не имеет значения. Рис. 8. Команда Get через CAN на стороне MCU. STM8 посылает сообщения следующим образом. Сообщение 1: Std ID = 0x02, DLC = 1, data = ACK. Команда читает память (RAM, память программ Flash, данные EEPROM или регистры). Когда загрузчик получает команду Read Memory, он передает необходимые данные ((N + 1) байт) хосту, начиная с указанного в команде адреса. Примечание: допустимыми считаются адреса RAM, памяти программ Flash, EEPROM данных и адреса регистров (см. даташит на используемый MCU). Если загрузчик принял недопустимый адрес, то произойдет ошибка (см. таблицу 10). [USART/LINUART/UART1/UART2/UART3] Рис. 9. Команда Read Memory через USART/LINUART/UART1/UART2/UART3 на стороне хоста. Хост посылает байты в STM8 следующим образом: Байты 1-2: 0x11+0xEE (команда и её комплемент). Рис. 10. Команда Read Memory через USART/LINUART/UART1/UART2/UART3 на стороне MCU. [SPI] Рис. 11. Команда Read Memory через SPI на стороне хоста. Хост посылает байты в STM8 следующим образом: Байт 1: 0x11 - Command ID. Рис. 12. Команда Read memory через SPI на стороне MCU. [CAN] Сообщение CAN отправляется хостом следующим образом: • ID содержит код команды (0x11). Рис. 13. Команда Read Memory через CAN на стороне хоста. Хост посылает сообщения команды следующим образом. Std ID = 0x11, DLC = 0x05, data = MSB, 0xXX, 0xYY, LSB, N (где 0 < N ≤ 255). Рис. 14. Команда Read Memory через CAN на стороне MCU. STM8 отправляет сообщения следующим образом. Сообщение ACK: Std ID = 0x02, DLC = 1, data = ACK. Примечание: загрузчик посылает столько сообщений данных, сколько байт можно прочитать. Команда позволяет хосту стереть сектора Flash памяти программ и data EEPROM. Загрузчик получает сообщение команды стирания, когда ID содержит тип команды 0x43, и поле данных содержит сектора для очистки (см. таблицу 9 с кодами секторов STM8). С размером сектора 1 килобайт получается гранулярность команды стирания в 8 блоков (1 блок = 128 байт). Если хосту надо стереть только 1 байт, то может использоваться команда записи (запись 0x00). Описание команды Erase Memory: 1. Загрузчик принимает 1 байт, который содержит количество (N) стираемых секторов. N зависит от используемого MCU. Примечание: подпрограмма "стереть соответствующие сектора" выполняется в RAM. Таким образом, пользователь должен загрузить подпрограмму стирания в RAM перед отправкой команды стирания. Обратите внимание, что для некоторых версий загрузчика это не требуется (см. далее "Подпрограммы erase/write в памяти RAM"). Предупреждение: если хост отправит команду стирания, которая содержит некоторый корректный код сектора и один или большее количество запрещенных кодов сектора (см. таблицу 9 с кодами секторов STM8), то команда завершится неудачей, и ни один блок не будет стерт. [USART/LINUART/UART1/UART2/UART3] Рис. 15. Команда Erase Memory через USART/LINUART/UART1/2/3 на стороне хоста. Примечания: (1) "Total erase" стирает память программ и data EEPROM. Загрузчик сотрет всю память сектор за сектором. Хост посылает байты следующим образом. Байт 1: 0x43 - Command ID. Примечание: N зависит от используемого MCU. M = (размер памяти программ Flash в килобайтах) + (размер data EEPROM в килобайтах) -1. Пример для STM8S Series-high density: M = 129, потому что размер памяти программ Flash 128 килобайт и data EEPROM 2 килобайта (128 + 2 - 1). Пример для STM8S Series-medium density: M = 32, потому что память программ Flash 32 килобайта, и data EEPROM 1 килобайт (32 + 1 - 1). Байт 4 или N+1 байт: 0x00 или (N+1 байт и затем контрольная сумма: XOR(N,[N+1 байт данных])). Пример для STM8L и STM8AL Series-low density: M = 8, потому что память программ Flash 8 килобайт и data EEPROM (256 байт) в следующем начальном 1 килобайте (8 + 1 - 1). Байт 4 или N+1 байт: 0x00 или (N+1 байт и затем контрольная сумма: XOR(N,[N+1 байт данных])). Рис. 16. Команда Erase Memory через USART/LINUART/UART1/2/3 на стороне MCU. [SPI] Рис. 17. Команда Erase Memory через SPI на стороне хоста. Примечание: когда используется команда стирания через SPI, необходимо подождать известный интервал времени (см. блок "Задержка" на рис. 17) перед отправкой последнего token-байта. Этот интервал задержки зависит от количества стираемых секторов (N). Delay = 30 * (N + 1)[мс], здесь 0 ≤ N ≤ 32. N = 32 в случае полной очистки (total erase). См. также "Приложение C. Опции тайминга SPI". Хост посылает байты следующим образом. Байт 1: 0x43 - Command ID. Рис. 18. Команда Erase Memory через SPI на стороне MCU. [CAN] Рис. 19. Команда Erase Memory через CAN на стороне хоста. Примечания: (1) Загрузчик стирает память сектор за сектором. Хост посылает байты следующим образом. Сообщение полного стирания: Std ID = 0x43, DLC = 0x01, data = 0xFF. Рис. 20. Команда Erase Memory через CAN на стороне MCU. Команда позволяет хосту записать данные в любое допустимое место на карте памяти (RAM, память программ Flash, data EEPROM или регистры) начиная с указанного адреса. Поступающие данные всегда записываются в RAM перед тем, как они загружаются в ячейки памяти, которые указал хост. Затем загрузчик проверяет, хочет ли хост записать данные в RAM, или же память программ Flash/data EEPROM. Максимальный размер записываемого блока для STM8 равен 128 байтам данных. Чтобы записать данные в ячейки памяти Flash/EEPROM, загрузчик выполняет две разные операции записи: 1. WordWrite/FastWordWrite (запись слова / быстрая запись слова): записывает байт в память Flash/EEPROM. Это используется, когда количество отправляемых хостом байт меньше 128. В этом случае загрузчик выполняет операцию N раз. См. даташит на используемый MCU, чтобы использовать допустимый адрес. Если начальный адрес недопустимый, то произойдет ошибка add_error (см. таблицу 10). Примечание: код команды записи принятых данных по указанному адресу выполняется в RAM. Таким образом, пользователь должен предварительно загрузить подпрограмму записи в RAM перед отправкой команды записи. Обратите внимание, что для некоторых загрузчиков это не требуется (см. далее секцию "Подпрограммы erase/write в памяти RAM"). [USART/LINUART/UART1/UART2/UART3] Рис. 21. Команда Write Memory через USART/LINUART/UART1/UART2/UART3 на стороне хоста. Примечание: см. даташит на используемый MCU, чтобы использовать допустимый адрес. Если начальный адрес недопустимый, то произойдет ошибка add_error (см. таблицу 10). Хост посылает байты следующим образом. Байт 1: 0x31 - Command ID. Рис. 22. Команда Write Memory через USART/LINUART/UART1/UART2/UART3 на стороне MCU. [SPI] Рис. 23. Команда Write Memory через SPI на стороне хоста. Примечание (1): здесь нужна задержка Delay или опрос флага занятости BUSY, если устройство это поддерживает. Задержка Delay в миллисекундах вычисляется по формуле: Delay = 8.45 x n. Здесь n это количество циклов записи (количество байт или количество блоков, см. таблицу 8). Таблица 8. Примеры задержки.
В режиме SPI, если MCU поддерживает отправку флага занятости BUSY во время программирования памяти Flash/EEPROM, то задержка может быть заменена на опрос состояния MCU (в него посылается набор token-байтов). Во время программирования MCU посылает флаг BUSY (0xAA) через SPI. Когда программирование завершено, MCU посылает ACK/NACK, чтобы показать результат операции - завершилось программирование успешно или неудачно. В настоящее время такой опрос возможен только для устройств STM8AF/S-medium density с модифицированными подпрограммами RAM (см. "Приложение C. Опции тайминга SPI"). На устройствах STM8L/AL-low density и STM8L/AL-high/medium+ density флаг BUSY flag посылается через интерфейс SPI. Хост посылает байты следующим образом. Байт 1: 0x31 - Command ID. Важное замечание: перед отправкой token-байта хост должен подождать, пока загрузчик завершит запись всех данных в память. См. выше описание задержки Delay (или опроса занятости). Последний байт (token): 0xXY; хост ждет ACK или NACK. Рис. 24. Команда Write Memory через SPI на стороне MCU. [CAN] Рис. 25. Команда Write Memory через CAN на стороне хоста. Хост посылает сообщения следующим образом. Соообщение команды: Std ID = 0x31, DLC = 0x05, data = MSB, 0xXX, 0xYY, LSB, N. N = 0 ... 127, количество байт данных -1. Если N > 127, то в загрузчике произойдет ошибка cmd_error. Примечания: (1) DLC_1 + DLC_2 + ... DLC_M = 128 максимум. Рис. 26. Команда Write Memory через CAN на стороне MCU. Эта команда позволяет поменять скорость интерфейса CAN во время активной сессии с загрузчиком. Команда Speed может использоваться только если для обмена используется интерфейс CAN. Рис. 27. Команда Speed через CAN на стороне хоста. Примечание: после отправки новой скорости (baud rate), загрузчик посылает сообщение ACK на старой скорости. Поэтому хост ждет, пока MCU не отправит ACK, и только после этого меняет свою скорость. Хост посылает сообщение следующим образом. Сообщение команды: Std ID = 0x03, DLC = 0x01, data = 0xXX. Здесь 0xXX подразумевает следующие значения, в зависимости от установленной на основе тактовой частоты HSE скорости: 0x01 -> baud rate = 125 kbps Рис. 27. Команда Speed через CAN на стороне MCU. Команда запускает загруженный код (или любой другой код) путем передачи управления по адресу, указанному хостом. После того, как команда Go выполнена, области памяти программ и данных находятся в разблокированном состоянии. Приложения должны заблокировать области памяти программы и данных, чтобы установить для памяти состояние защиты по умолчанию. Для адреса перехода должен использоваться допустимый адрес RAM, памяти программ Flash, EEPROM данных и адрес регистра (см. даташит на используемый NCU). Если загрузчик примет недопустимый адрес, то произойдет ошибка add_error (см. таблицу 10). [USART/LINUART/UART1/UART2/UART3] Рис. 29. Команда Go через USART/LINUART/UART1/UART2/UART3 на стороне хоста. Хост посылает байты следующим образом. Байт 1: 0x21 - Command ID. Рис. 30. Команда Go через USART/LINUART/UART1/UART2/UART3 на стороне MCU. [SPI] Рис. 31. Команда Go через SPI на стороне хоста. Хост посылает байты следующим образом. Байт 1: 0x21 - Command ID. Рис. 32. Команда Go через SPI на стороне MCU. [CAN] Рис. 33. Команда Go через CAN на стороне хоста. Хост посылает сообщение следующим образом. Сообщение команды Go: Std ID = 0x21, DLC = 0x04, data = MSB, 0xXX, 0xYY, LSB. Рис. 34. Команда Go через CAN на стороне MCU. Таблица 9. Коды секторов STM8.
[Модель программирования (серии STM8AF, STM8AL, STM8L и STM8S)] Код загрузчика (boot code) разработан с одинаковым логическим протоколом для обмена кадрами команд между хостом и любым устройством (MCU) серий STM8AF, STM8AL, STM8L и STM8S. Загрузчик может загружать за один раз до 128 байт. Переменные загрузчика занимают RAM от адреса 0x000000 до адреса 0x00009F. Если загрузчик был разрешен (в соответствии с таблицей 4), и истекли таймауты (не произошла активация хоста, или произошел переход в приложение пользователя), то содержимое RAM может остаться измененным загрузчиком. Например, если пользовательское приложение запустилось, и произошел сброс, то содержимое RAM в диапазоне адресов 0x000000 .. 0x00009F будет изменено загрузчиком до перезапуска приложения. Если загрузчик запрещен с помощью байта опций или активацией защиты ROP, то необходимо произвести следующие незначительные изменения в приложении пользователя: • Версии MCU серий STM8L и STM8AL, и последних серий STM8AF и STM8S (см. таблицу 3): RAM не меняется загрузчиком. Примечание: не используемое (пустое) пространство bootloader ROM заполнено недопустимым кодом операции (0x71). Если по любой причине (например, из-за шума EMC) ядро начнет выполнять код в области, заполненной 0x71, то произойдет ошибка недопустимой операции (illegal opcode) и последующий сброс. Это предотвращает вход загрузчика в бесконечное зацикливание (зависание) без возможности автоматического сброса, когда произошел случайный переход по "пустому" адресу. Таким образом может произойти восстановление нормального выполнения программы. [Подпрограммы erase/write в памяти RAM] Подпрограммы RAM erase/write прикреплены к этому документу как двоичный код в формате S19. Имя файла определяет группу STM8 (т. е. 128 килобайт, 32 килобайта, 8 килобайт) и номер версии загрузчика, для которого эта подпрограмма написана. Чтобы стереть или запрограммировать память программ Flash или data EEPROM, должны быть загружены соответствующие подпрограммы в RAM, начиная с адреса 0x0000A0. Пример именования RAM подпрограммы erase/write: • 128-килобайтные устройства (high density) серий STM8AF и STM8S: E_W_ROUTINEs_128K_ver_2.2.s19. Чтобы выполнить любую команду (Get, Read, Erase, Write, Speed и Go) загрузчик использует часть RAM для своих собственных переменных и подпрограмм RAM erase/write. Поэтому запрещено выполнять команды записи (за исключением команд записи, которые используются для загрузки подпрограмм erase/write) с адресами назначения в следующих областях RAM: • MCU серий STM8AF и STM8S: от 0x000000 до 0x0001FF. [Обработка ошибок] Загрузчик выполняет несколько внутренних проверок, включая проверку на допустимый диапазон адреса в командах, проверку контрольных сумм команд и верификацию записи. Загрузчик не проверяет доступ в область UBC. Если запись производится в область, защищенную от записи, то верификация завершится с ошибкой и загрузчик вернет NACK. Таблица 10 описывает типы ошибки и соответствующее поведение загрузчика. Таблица 10. Ошибки загрузчика.
[Время программирования] Сколько займет времени программирование, зависит от скорости используемого для обмена периферийного устройства. Примеры времени программирования включают измерения для следующих интерфейсов и скоростей: • USART/LINUART/UART1/UART2/UART3: 128 килобит/сек, 256 килобит/сек, 500 килобит/сек. Примечание: измерения производились на блоках 48 килобайт или 32 килобайта, независимо от типа MCU и используемого периферийного устройства. Таблицы 11, 12 и 13 показывают время программирования данных в память прогамм Flash соответственно для USART/LINUART/UART1/UART2/UART3, SPI и CAN. Таблица 11. Время программирования через USART/LINUART/UART1/UART2/UART3.
Таблица 12. Время программирования через SPI.
Таблица 13. Время программирования через CAN.
Функция защиты от чтения ROP предотвращает от несанкционированного чтения памяти MCU через интерфейс SWIM. Во время своей инициализации загрузчик проверяет состояние ROP (анализом содержимого байта опций ROP), и если защита ROP разрешена, то загрузчик не активируется. Это предотвращает возможность считывания прошивки и данных через загрузчик (или возможности записи и выполнения троянского кода). Однако на практике может понадобится не только использование защиты ROP, но и обновление прошивки, чтобы можно было записать новое firmware через IAP. Это может быть сделано через приложение пользователя и взаимодействие с загрузчиком по следующим правилам. [Правила для обновления устройств, которые защищены ROP] 1. Устройство должно быть защищено активацией ROP (что запрещает чтение памяти через SWIM). 2. Загрузчик не активируется после сброса из-за проверки состояния ROP (чтобы запретить чтение памяти через загрузчик). 3. Приложение пользователя отвечает за разрешение обновления после аутентификации пользователя, например после проверки ввода пароля. 4. Приложение пользователя после успешной проверки аутентификации позволяет запустить загрузчик (выполнением jump по специфическому адресу загрузчика). После этого загрузчик может обновить приложение пользователя обычным образом. По приведенным выше правилам приложение пользователя может быть обновлено через резидентный загрузчик, находящийся в ROM. Единственное условие заключается в том, что приложение пользователя (firmware) должно взаимодействовать с процессом выгрузки, как описано ниже: • В приложении должна быть реализована процедура аутентификации (например, отправка специальной команды с паролем через интерфейс коммуникации). ROM-загрузчик может быть активирован хостом после сброса устройства (см. выше секцию "Активация загрузчика"). Однако загрузчик может также использоваться в приложении пользователя для различных целей. В таблице 14 перечислены основные точки входа в загрузчик, и описано, как они могут использоваться в приложении пользователя. Таблица 14. Точки входа в загрузчик (bootloader entry point).
Примечания: (1) Адрес зависит от версии загрузчика, и может быть изменен в его следующей, более новой версии. За последней информацией свяжитесь с локальным офисом STMicroelectronics. Перед jump в точку входа загрузчика приложение должно сконфигурировать все используемые периферийные устройства (таймеры, периферийные устройства коммуникационных интерфейсов, ножки GPIO этих периферийных устройств) в их состояние по умолчанию после сброса, чтобы загрузчик мог корректно продолжить свое выполнение. Загрузчик был разработан с таким расчетом, что на входе получает состояние MCU после сброса (когда все периферийные устройства находятся в своем состоянии по умолчанию). Для всех MCU перед тем, как сделать jump на точку входа в загрузчик, необходимо обновить теневые регистры прескалера TIM2 и TIM3 (prescaler shadow registers) в значение 1 с помощью следующего рекомендуемого кода: ... // Запуск события обновления (update event),
// чтобы прескалер TIM3 обновился в значение 1: TIM3->EGR = 0x01; // Очистка генерируемого флага update event
// в бите TIM3_SR1 с помощью чтения и записи
// в него нуля: TIM3->SR1; TIM3->SR1 = 0x00; // jump, передача управления на адрес точки входа: _asm("jp 0x601E"); ... [SPI с проверкой состояния занятости] Во врезках с описанием команд Erase Memory и Write Memory, работающих через SPI, содержатся рисунки с алгоритмом работы этих команд. Недостаток SPI в том, что хост управляет транзакциями с помощью опроса данных из MCU. Если MCU занят (например, он программирует память Flash), то хост получит ответ в виде последнего байта, который был записан в регистр данных SPI (это последний отправленный байт с момента предыдущего опроса). Так что у хоста нет способа определить, был ли принятый от MCU байт корректным (новым) ответом, или же это байт от предыдущего ответа. На практике, если хост запрашивает MCU выполнить текущую команду стирания или записи (ACK или NACK от MCU после завершения операции), то хост знает, что устройство не занято и завершило операции. Таким образом, хост должен добавить подходящую минимальную задержку, чтобы позволить MCU закончить операцию (см. блок "Delay" на рис. 17 и 23). Иначе ответ не имеет смысла, и обмен получится рассинхронизированный. Такое поведение специфично только для тех интерфейсов, работой которых управляет хост (мастер шины), таких как интерфейс SPI. Другие интерфейсы, используемые в загрузчике, включая UART и CAN, не управляются жестко мастером (и с ними MCU имеет возможность самому выполнить передачу данных без опроса хостом). [Модифицированные RAM-подпрограммы erase/write] Чтобы избавиться от зависимости реализации задержки на стороне хоста и ускорить обмен SPI (потому что задержка с запасом оказывается дольше времени завершения операции), разработаны специальные RAM-подпрограммы erase/write. Эти подпрограммы выполняют длительные по времени операции так же, как и стандартные операции erase/write. Когда MCU занят, он отправляет в виде ответа хосту байт занятости BUSY (0xAA). Хост может периодически запрашивать от устройства ответ, если пришел ответ BUSY, то это значит, что операция еще не завершена. После завершения операции MCU ответит байтом ACK или NACK, в зависимости от результата операции. Тогда блок алгоритма "Delay" на рисунках 17 и 23 заменяется циклом опроса, пока не будет принят ответ ACK или NACK. Рис. 35. Удаление задержки (Delay) в модифицированных RAM-подпрограммах. Модифицированные RAM-подпрограммы erase/write для поддержки опроса SPI предоставляются для 32-килобайтных MCU STM8AF/S. MCU STM8L/AL сами поддерживают подпрограммы RAM с ответом состояния BUSY (для них копировать подпрограммы erase/write не нужно). Для поддержки загрузчика фирма STMicroelectronics предоставила демонстрационное приложение PC, известное как "Flash loader demonstrator", которое позволяет обновить firmware в STM8 через интерфейс UART (на стороне PC это традиционный RS-232 или виртуальный COM-порт USB CDC). Это ПО работает под операционной системой Microsoft® Windows®, и его можно загрузить с сайта www.st.com. С этим ПО любое firmware, сохраненное в файл *.s19, может быть выгружено в устройство STM8AF/AL/L/S. ПО также выполняет проверку выгруженного firmware и автоматическое стирание памяти. Рис. 36. Программа "Flash loader demonstrator". Ограничение для загрузчика введено не из-за того, что загрузчик реализован неправильно, и не из-за несовместимости со спецификациями. Причина в специфике применения STM8 ROM bootloader конечным пользователем. Чтобы предотвратить возникновение проблем, используйте способ обхода ограничения загрузчика UART, описанный далее, когда это необходимо. [Автоопределение скорости UART] Как упоминалось выше в секции описания настроек USART/UART, загрузчик опрашивает все периферийные устройства (UART, SPI, CAN) в ожидании байта синхронизации. Обмен с загрузчиком начинается, когда принятый байт синхронизации равен 0x7F. Для обмена данными через UART скорость, с которой передаются данные, изначально неизвестна для загрузчика. Для SPI и CAN ситуация другая, потому что скорость SPI задается тактами хоста, а для CAN скорость по умолчанию фиксирована на 125 килобит/сек. Перед инициализацией интерфейса UART загрузчик анализирует длительности на ножке приема UART (ножка RxD GPIO), ожидая байта синхронизации 0x7F, и по его измеренным длительностям нулей и единиц вычисляет скорость передачи. Это называется автоопределением скорости UART. 1. Мастер посылает 0x7F в виде последовательного кадра (LSB идет первым) на вход интерфейса UART. Байт 0x7F состоит из следующих частей: – Start-бит (лог. 0). 2. Загрузчик опрашивает уровень на ножке RxD, ожидая появления start-бита (лог. 0). 3. В момент перепада от 0 к 1 (окончание start-бита) загрузчик запускает таймер, чтобы по его счетчику измерить длительность 7 логических единичек. 4. Загрузчик останавливает таймер по спаду уровня RxD (завершение 7 следующих друг за другом бит лог. 1, в момент начала MSB). Количество тиков таймера соответствует длительности 7 логических единиц байта синхронизации 0x7F. По счетчику таймера загрузчик вычисляет длительность одного бита (количество тиков делится на 7), по этой длительности вычисляет скорость UART (baudrate), и соответствующим образом инициализирует скорость периферийного устройства UART. После этого загрузчик готов к принятию следующей команды от хоста. [Описание ограничения UART] Автоматическое вычисление скорости подразумевает, что хост отправит 0x7F в качестве байта синхронизации. Однако вычисление скорости будет неправильным, если хост отправит байт, отличающийся от 0x7F, потому что загрузчик ожидает семи следующих друг за другом лог. 1 вслед за start-битом фрейма. В этой ситуации возобновить обмен поможет только сброс MCU STM8. Следовательно, хост должен отправить 0x7F после сброса, чтобы корректно запустить загрузчик на интерфейсе UART, либо не должен ничего посылать в течение 1 секунды после сброса, чтобы загрузчик не запустился, и начало выполняться приложение пользователя. Любой другой байт, отправленный загрузчику в течение 1 секунды после сброса, приведет к входу загрузчика в бесконечный цикл ожидания команды не неправильно определенной скорости. Такая ситуация может возникнуть в приложении пользователя, если STM8 было сброшено в тот момент, когда большой объем данных передается через интерфейс UART. Тогда устройство войдет в бесконечный цикл загрузчика из-за приема нескольких "байт синхронизации". [Обход ограничения UART] Проблема, описанная выше, может быть исправлена по следующей методике. Она основана на модификации кода приложения и конфигурации MCU. Это рекомендуется, если Ваше приложение при запуске входит в бесконечный цикл, когда начинается обмен через UART. Необходимо выполнить следующие шаги: 1. Запретите загрузчик байтами опций (на чистых MCU загрузчик запрещен). В результате при сбросе загрузчик не активируется, и устройство не войдет в бесконечный цикл, когда примет через UART случайные байты. После сброса загрузчик сразу запустит код приложения без всякой задержки, что также выглядит для приложения как дополнительное преимущество. Если необходимо обновить код приложения, выполните следующую последовательность действий: 1. Нажмите специальную кнопку, которая активирует загрузчик с помощью передачи управления на указанную bootloader entry point. Необходимо гарантировать, что к UART при этом подключен хост, и он не отправляет никаких случайных байт. Описанный способ запуска загрузчика с помощью кнопки может быть заменен другим условием запуска загрузчика, например с помощью отправки через интерфейс специальной команды или пароля аутентификации (чтобы обновить firmware мог только авторизованный персонал). Операция программирования может потерпеть крах в процессе обновления (например, из-за неожиданного отключения питания устройства). Тогда в загрузчик снова войти не получится, потому что код приложения не был корректно обновлен. Чтобы предотвратить возникновение такой проблемы, рекомендуется, чтобы хост выполнил следующие шаги перед входом в загрузчик: 1. Разрешение ROM bootloader через байты опций перед загрузкой кода приложения в устройство. Определенная группа STM8 связана с определенным кодом загрузчика. Этот код с течением времени подвергается улучшениям, и появляются новые версии загрузчика. Отличия разных версий загрузчика суммарно показаны в таблице 15 вместе с ограничениями, улучшениями и добавленными функциями. Таблица 15. Описание ограничений, улучшений и добавленных функций в разных версиях загрузчика.
[Словарик] ACK acknowledge, положительное подтверждение (отрицательным подтверждением будет NACK). BCD binary-coded decimal, двоично-десятичное число. Из Википедии: 8421-BCD это форма записи рациональных чисел, когда каждый десятичный разряд числа записывается в виде его четырёхбитного двоичного кода. Таким образом, каждая тетрада двоично-десятичного числа может принимать значения от 00002 (010) до 10012 (910). Например, десятичное число 31110 будет записано в двоичной системе счисления в двоичном коде как 1 0011 01112, а в двоично-десятичном коде как 0011 0001 0001BCD. BL bootloader, загрузчик. bps bit per second, скорость в бит/сек. DFU Direct Firmware Update, дословный перевод "прямое обновление микропрограммы". Термин обозначает технологию обновления прошивки MCU с использованием встроенного загрузчика. EMC electromagnetic compatibility, электромагнитная совместимость. Термин, обозначающий устойчивость к помехам (EMI). EM сокращение от Erase Memory (рис. 1). EMI electromagnetic interference, электромагнитные помехи. GPIO general purpose input/output, входы/выходы общего назначения. IAP in-application programming, программирование в системе. То же самое, что и ISP. ISP in-system programming, программирование в системе. То же самое, что и IAP. HSE high speed external, высокоскоростная внешняя тактовая частота (определяется подключенным кварцем или внешним генератором). HSI high speed internal, внутренняя высокоскоростная тактовая частота. LSB least significant bit, самый младший значащий бит. Также, в зависимости от контекста, может означать самый младший байт. MCU microcontroller unit, микроконтроллер. MSB most significant bit, самый старший значащий бит. Также, в зависимости от контекста, может означать самый старший байт. NACK negative acknowledge, отрицательное подтверждение (положительным подтверждением будет ACK). NSS node select slave, сигнал для выборки подчиненного устройства на шине SPI. RAM random access memory, память с произвольным доступом, оперативная память, ОЗУ. ROM read-only memory, память только для чтения, постоянная память, ПЗУ. ROP readout protection, защита от чтения кода. routine подпрограмма. SWIM single wire interface module, однопроводный интерфейс отладки, встроенный в микроконтроллер. SW reset программный сброс. token токен, пустой произвольный байт, служит для получения и приема подтверждения ACK или NACK. Токен используется из-за особенности реализации SPI - обмен в обе стороны происходит одновременно, т. е. подчиненное устройство (в нашем случае подчиненным устройством служит MCU) может отправить свое подтверждение только если хост передаст произвольный байт (токен). UBC user boot code, память, предназначенная для загрузчика. WM сокращение от Write Memory (рис. 1). [Ссылки] 1. UM0560 User manual STM8 bootloader site:st.com. |