======Загрузка программы в ОЗУ и запуск через UART====== В статье [[prog:uart:loader_uart|Тестируем Bootloader в режиме UART]] мы опробовали команды управления UART загрузчиком и запустили программу, записанную в Flash. Команды загрузчика позволяют записать массив байт в ОЗУ и запустить программу с заданного адреса. Этого достаточно, чтобы записать в ОЗУ программу и её запустить. Это мы сейчас и сделаем. Для запуска в ОЗУ, нам потребуется программа, которая использует только адреса ОЗУ. Мы такой пример уже делали в статье - [[prog:start:run_ram_keil|Запуск программы в ОЗУ из Keil]], программа называется //HelloWorld_RAM//. Давайте откроем проект и внесем одно изменение. =====Получение bin файла===== Для начала необходимо получить бинарный файл нашего примера. В этом файле нет ничего лишнего, а только байты кода нашей программы. Есть различные конвертеры, которые позволяют из hex файла, получить bin файл. Можно было бы использовать их. Но мы воспользуемся штатной возможностью Keil, описанной здесь - [[http://www.keil.com/support/docs/3213.htm|Keil: GENERATING BINARY OUTPUT DURING A BUILD]] Bin файл будет автоматически генерироваться при сборке проекта. В настройках проекта идем в //Options - User//, находим пункт //AfterBuild/Rebuild// и ставим галочку в опции //Run #1//. В поле команды данного пункта необходимо вписать следующее: $K\ARM\ARMCC\bin\fromelf.exe --bin --output=@L.bin !L {{prog:uart:ram_makebin.png}} Теперь делаем Rebuild проекта //HelloWorld_RAM// и в папке проекта находим файл "HelloWorld_RAM.bin". Кейл и проект можно закрыть, они больше не потребуются. =====Загрузка bin файла в ОЗУ===== Далее нам необходимо узнать размер файла, поскольку для команды LOAD нам потребуется указать количество байт записываемых в ОЗУ. Кликаем правой кнопкой мыши на "HelloWorld_RAM.bin", выбираем свойства и смотрим точный размер файла в байтах. {{prog:uart:ram_binsize.png}} В шестнадцатеричной системе 3116 равно 0х0С2С. Теперь у нас есть все данные для загрузки программы. Открываем программу //Terminal v1.9b// и повторяем все действия, описанные в статье [[https://startmilandr.ru/doku.php/prog:uart:loader_uart|тестируем Bootloader в режиме UART]] до получения приглашения от микроконтроллера. При желании можно также увеличить скорость обмена по UART, чтобы загрузка прошла быстрее. Я выставил 19200 бод. Давайте напишем макрос //M10//. Код команды = 'L', адрес = 0x2000_0000, количество байт = 0x0000_0C2C. Записать программу необходимо с адреса, который был указан в поле //IROM1// закладки //Options - Target// при сборке проекта "HelloWorld_RAM". У нас там был указан стартовый адрес ОЗУ, поэтому и параметр адрес = 0x2000_0000. Код макроса М10: L$00$00$00$20$2C$0C$00$00 Нажимаем М10. Нам пришло подтверждение команды загрузки - 'L'. Теперь UART загрузчик ожидает приема 3116-ти байт. Посылаем ему наш файл "HelloWorld_RAM.bin". Для этого находим кнопку //Send File// и в открывшемся окне выбираем наш "HelloWorld_RAM.bin". Жмем ОК и файл передается в UART. {{prog:uart:ram_loadbin.png}} Спустя несколько секунд, приходит символ 'K' - подтверждение от микроконтроллера об успешном получении 3116 байт. Теперь наша программа находится в ОЗУ. В терминале это выглядит так: >LK =====Запуск===== Для запуска напишем макрос //М11//, код команды = 'R', стартовый адрес = 0x2000_0000. Код макроса М11: R$00$00$00$20 >R 00 00 00 20 < 52 = 'R' - подтверждение команды запуска ОСОБЕННОСТЬ: //В некоторых микроконтроллерах требуется указать не стартовый адрес программы, а сразу адрес обработчика Reset_Handle. Этот адрес необходимо взять из загружаемого образа программы, с адреса 4. Первые 4 байта используются для указателя стека, а вторые 4 байта - это и есть необходимый адрес обработчика. Похоже, что код внутри загрузчика проверяет этот адрес.// Запускаем М11, нам приходит подтверждение команды запуска, символ 'R'. Светодиод на плате начинает мигать, значит, наша программа успешно стартовала из ОЗУ. Таким вот не сложным образом мы научились загружать программу в ОЗУ и запускать ее на исполнение. На основе данного примера можно реализовать прошивку и Flash памяти процессора. Только загрузить потребуется две программы: - пользовательскую программу, которую необходимо зашить в Flash. - программу "прошиватель", которая умеет писать в Flash. После загрузки обеих программ, запускается программа "прошиватель". Эта программа "прошиватель" будет брать код пользовательской программы и писать ее в Flash. Давайте это осуществим - [[prog:uart:flash_writer|Прошивка программы в Flash и запуск через UART]]. **На самом деле загрузчик Bootloader, который работает в МК и обеспечивает связь по UART является программой, написанной на Си. Поэтому младшие адреса заняты под глобальные переменные и кучу, а старшие адреса ОЗУ заняты под стек. Загружая программу с адреса 0х2000_0000, мы рискуем затереть данные программы загрузчика. Поэтому при загрузке в память следует отступить от края ОЗУ. На форуме приводится рекомендация при загрузке программы по UART использовать диапазон адресов 0x2000_0100 - 0x2000_7E00.** Будем считать, что нам повезло. Видимо, никаких важных данных в начальных адресах ОЗУ не содержалось, поэтому пример отработал успешно. UPD: Добавлена программа на Python для стирания памяти через UART - [[https://github.com/StartMilandr/MDR_Pack_v6/tree/master/Utils/pyUnbrickVE9x|GitHub]]. Эта программа делает автоматически все, что описано в данной статье. Т.е. загружает по UART в ОЗУ микроконтроллера программу, которая при запуске стирает флеш память.