Программирование AVR Загрузчики (bootloader) для микроконтроллеров AVR Tue, December 12 2017  

Поделиться

нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


Загрузчики (bootloader) для микроконтроллеров AVR Печать
Добавил(а) microsin   

Описана технология bootloader, встроенная во все микроконтроллеры Atmel AVR семейства ATmega. Материал для статьи взят с сайта scienceprog.com.

Возможно, что самый удобный и правильный метод программирования микроконтроллера - использовать программу бутлоадера. Поскольку Вам не надо использовать специальные адаптеры для программирования или специальные знания – нужно просто подключить стандартный кабель от Вашего PC к целевой плате и запустить на PC специальную программу, которая соединяется с программой бутлоадера, записанной в микроконтроллере. Идея проста:

avr_bootloader_model.jpg

Если микроконтроллер после сброса предварительно переконфигурирован (если установлены определенные фьюзы), он стартует не с адреса 0x0000, а со специального адреса, в котором обычно располагается bootloader. На диаграмме condition - это условие загрузки, которое определяется обычно опросом состояния специальной внешней перемычки, подключенной к ножке микроконтроллера.

Все микроконтроллеры семейства AVR ATmega имеют возможность запрограммировать bootloader в старшие адреса адресного пространства. Адрес старта программы зависит от установок внутренних перемычек чипа AVR (fuse settings). Если установки указывают стартовать с другого адреса, то после сброса программный счетчик переставляется на секцию бутлоадера, и тогда первым выполняется bootloader. Бутлоадеры могут иметь различный размер и использовать разные алгоритмы и интерфейсы, через которые будет загружаться основная программа. Источниками для загрузки могут быть карты Flash (MMC/SD), I2C, USART (COM-порт или RS232), SPI и USB. Условие для загрузки может быть получено, например, путем опроса специальной внешней перемычки, или наличием на карте памяти MMC/SD специального файла с прошивкой.

[USB bootloader]

Несомненно, самый удобный для пользователя интерфейс загрузки - USB. Этот интерфейс очень популярен, работает на всех операционных системах. Но протокол USB довольно сложен, поэтому встраивание bootloader в микроконтроллер, не имеющий аппаратной поддержки USB, потребует значительного объема кода (до 2 килобайт). Наиболее распространена программная реализация протокола USB от компании Objective Development - V-USB [6]. Есть также другая программная реализация - USBtiny [7].

Для микроконтроллеров AVR с аппаратным интерфейсом USB (например, AT90USB162) компания Atmel предлагает фирменные загрузчики по USB. Некоторые микроконтроллеры поставляются с завода с уже прошитым в память загрузчиком (например, все тот же AT90USB162). Технологии, применяемые для такого bootloader, называются DFU и Flip. Подробнее см. [5].

[Разнообразие бутлоадеров для AVR]

Многие AVR bootloader используют COM-порт для соединения с PC. Это хорошо работает, если используется аппаратный мост USB-USART. Если пишется бутлоадер самостоятельно, то не факт, что он сразу заработает. Обязательно потребуется отладка, и внимательное чтение документации на микроконтроллер. В списке можно увидеть уже готовые популярные бутлоадеры, которыми можно воспользоваться (список может быть и бОльшим):
    * Atmex site:ladyada.net, COM, 19200bps, Assembler; JAvrProg(Java), ATtiny2313 (8-16Mhz);
    * AVR Bootloader Programmer Peter Dannegger site:mikrocontroller.net, COM, Assembler; ATmega8/16/32/128;
    * AVRProg-compatible Bootloader Martin Thomas site:siwawi.arubi.uni-kl.de, COM, WinAVR (C); AVRProg; Various AVRs and speeds;
    * USBisp Bootloader Matthias Weisser site:matwei.de, USB, COM, AVR-GCC(C); AVRProg; STK-500; ATmega8, FT245BM;6MHz;
    * Bootloader ATmega8 AVR microprocessor site:stratoserver.net, COM, 19200bps, ASM, AVRProg;ATmega8 7.3728MHz;
    * Chip45boot site:chip45.com, COM, 11500bps, WinAVR; HyperTerminal; Various AVR
    * STK500-Bootloader Pascal Stang, COM, Hex; AVRProg; STK500; ATmega8-128; 7.3 – 22.1MHz
    * AVR109 (AVR Butterfly) site:atmel.com, COM, IAR(C); ATmega series; 12MHz;
    * AVRUSBBoot - USB bootloader for Atmel AVR controllers site:fischl.de, USB, AVR-GCC; ATmega8(other Megas); 12MHz;
    * Megaload site:microsyl.com, COM, 11500bps, ICCAVR(C); Megaload.NET; Various AVR;
    * BootloadHID site:obdev.at, USB, HID, WinAVR; ATmega8;
    * Crypto-Boot site:wikidot.com, USB, IAR(C); Crypted AES; ATmega32; 12MHz.

Большинство бутлоадеров рассчитано на COM-порт, который уже устарел и в современных компьютерах встречается редко. Наиболее простой способ адаптировать эти бутлоадеры на USB - использование аппаратного моста USART <-> USB типа FT245BM. Но вероятно более удобно, когда USB подключен непосредственно к микроконтроллеру, и часть коммуникации бутлоадера сделана драйвером USB встроенного программного обеспечения.

Загрузчик (bootloader) - одна из основных вещей, что отличает Adruino от простого микроконтроллера AVR компании Atmel. Когда Вы собираете свою плату, или когда случайно купили на ebay плату, не прошитую загрузчиком, то Вам нужен внешний программатор ISP, чтобы прошить в память микроконтроллера загрузчик.

Загрузчик это по сути маленькая программа, предназначенная для только одной цели - перепрошить микроконтроллер программой пользователя. Загрузчик размещен в старших адресах пространства памяти программ (FLASH), а программа пользователя - в младших адресах (начиная с нулевого адреса). На рисунке показан типичный пример распределения памяти программ (FLASH) микроконтроллера ATmega328.

Arduino-ATmega328-Bootloader-Memory-Map

Микроконтроллер Arduino сконфигурирован фьюзами так, чтобы при запуске системы (включение питания, сброс) управление всегда получал загрузчик. Затем загрузчик некоторое время ждет (1..2 секунды) загрузки программы пользователя, и если загрузка не началась, то запускает программу пользователя (передает управление на адрес 0). Таким образом, всегда можно при желании перезаписать программу пользователя, и тем самым обновить или полностью изменить функционал устройства. Код загрузчика при этом остается нетронутым.

Условие запуска загрузчика. Есть загрузчики, которые сразу передают управление в программу пользователя (без задержки), если не выполнено условие загрузки. Это иногда делается для того, чтобы ускорить запуск программы пользователя. Условие загрузки может быть разным, но чаще всего это перемычка, замыкающая на землю определенный (известный заранее пользователю) вывод микроконтроллера. Если перемычка установлена, то условие загрузки выполняется, и загрузчик ждет начала загрузки, не передавая управление в программу пользователя.

[На что нужно обратить внимание при программировании загрузчика]

Выбор загрузчика. Поскольку могут быть различные варианты реализации целевой системы - может быть применена разная модель микроконтроллера (ATmega168, ATmega328, ATmega32U4 и т. п.). Загрузчики для разных моделей микроконтроллеров могут быть несовместимыми друг с другом.

Частота кварцевого резонатора. Обязательно убедитесь, что прошиваемый Вами загрузчик точно соответствует рабочей частоте системы, разная частота кварцевого резонатора (обычно 8 или 16 МГц, но могут быть и другие варианты). Рабочая частота микроконтроллера обычно зависит от конфигурации фьюзов и частоты внешнего кварцевого или керамического резонатора.

Фьюзы. Для правильного функционирования загрузчика важны 2 аспекта, которые конфигурируются фьюзами - выбор размера секции загрузки (фьюзы BOOTSZ1, BOOTSZ0), разрешение работы загрузчика (фьюз BOOTRST), а также конфигурирование тактовой частоты (фьюзы, управляющие генератором тактовой частоты и прескалером - CKDIV8, SUT1, SUT0, CKSEL3..0).

Если Вы неправильно прошьете фьюзы BOOTSZ1, BOOTSZ0, BOOTRST, то код загрузчика не будет запускаться, и загрузчик работать не будет. Точно также если Вы неправильно сконфигурируете фьюзами тактовый генератор и прескалер, то микроконтроллер может заработать на той частоте, на которую загрузчик не рассчитан, и работоспособность загрузчика также будет нарушена. Для вычисления правильного значения фьюзов Вам поможет калькулятор фьюзов [6].

В таблице я привел самые популярные загрузчики и конфигурации для них. Фьюзы указаны в шестнадцатеричном значении, где HFUSE это старший байт фьюзов, LFUSE младший байт фьюзов, EFUSE байт расширенных фьюзов.

Таблица 4. Загрузчики Arduino UART.

AVR Тактовая частота Прошивка Размер секции загрузки, байт Фьюзы (HEX)
ATmega8 8 ArduinoBOOT-mega8-8MHz.hex 1024 HFUSE=CA LFUSE=DF
16 ArduinoBOOT-mega8-16MHz.hex
ATmega168 8 ArduinoBOOT-mega168-8MHz.hex 2048

HFUSE=DD
LFUSE=E2
EFUSE=00

16 ArduinoBOOT-mega168-16MHz.hex
ATmega328 8 ArduinoBOOT-mega328-8MHz.hex 2048 HFUSE=DA
LFUSE=FF
EFUSE=05
16 ArduinoBOOT-mega328-16MHz.hex 2048

Прошивки загрузчиков Arduino можно найти в папке, где установлена система разработки Arduino, обычно это папка с полным путем наподобие c:\Program Files\Arduino1.0.6\hardware\arduino\bootloaders. Там же можно найти исходный код загрузчиков. Также готовые прошивки и исходный код всех загрузчиков можете скачать по ссылке [9], см. папку arduino\bootloaders\HEX архива, и ищите там имена файлов прошивок, указанные в таблицах 4, 5, 6 (имя файла прошивки указано в столбце Прошивка).

Таблица 5. Загрузчики Atmel DFU.

AVR Тактовая частота Прошивка Размер секции загрузки, байт Фьюзы (HEX)
ATmega32U4 8 BootloaderDFU-mega32u4-8MHz.hex 4096 HFUSE=D8
LFUSE=DE
EFUSE=F3
16 BootloaderDFU-mega32u4-16MHz.hex

Таблица 6. Загрузчики USBasp.

AVR Тактовая частота Прошивка Размер секции загрузки, байт Фьюзы (HEX)
ATmega168 12 USBaspLoader-mega168-12MHz.hex 2048 HFUSE=D6
LFUSE=DF
EFUSE=00
16 USBaspLoader-mega168-16MHz.hex
20 USBaspLoader-mega168-20MHz.hex
ATmega328 12 USBaspLoader-mega328-12MHz.hex HFUSE=DA
LFUSE=F7
EFUSE=03
16 USBaspLoader-mega328-16MHz.hex
20 USBaspLoader-mega328-20MHz.hex

[Исходный код загрузчиков]

В некоторых случаях может потребоваться перекомпиляция прошивки загрузчика - например, если Вы используете особую частоту кварца, или если Вам необходимо внести коррективы в поведение загрузчика.

В таблице я привел описание самых популярных загрузчиков, которые используются в Arduino-совместимых платах. Исходный код загрузчиков вместе с готовыми прошивками можно скачать по ссылке [9].

Таблица 7. Разновидности загрузчиков, которые можно использовать для платформы разработки Arduino.

Название AVR Описание
Arduino UART ATmega8, ATmega168, ATmega328 и другие Используется для большинства плат Arduino, когда код загружается через мост USB-UART.
Atmel DFU ATmega32U4 и другие Применяется для случаев, когда микроконтроллер AVR имеет на борту аппаратный интерфейс USB. Загрузчик основан на протоколе Atmel DFU Flip и открытой библиотеке LUFA.
USBasp ATmega168, ATmega328 Применяется для плат metaboard. Загрузчик основан на открытой библиотеке V-USB, эмулирует поведение популярного программатора USBasp.

Как компилировать. Для компиляции Вам потребуется тулчейн AVR-GCC, доступный для большинства операционных систем - Linux, Mac OS, Windows. На операционной системе Windows тулчейн можно получить, если скачать и установить пакет WinAVR или среду разработки Atmel Studio.

Компилируется загрузчик командами утилиты make. Обычно для этого нужно зайти в каталог с исходным кодом загрузчика, и выполнить 2 команды:

make clean
make hex

После этого в текущем каталоге появится файл с расширением HEX - готовая прошивка загрузчика, которую нужно записать в память микроконтроллера с помощью обычного ISP-программатора (не забудьте также правильно установить фьюзы микроконтроллера!).

Инструкции по компиляции и настраиваемым опциям можно обычно получить, изучая содержимое файла Makefile проекта загрузчика, и сопутствующие файлы документации readme.txt.

[Пример конфигурирования загрузчика Arduino UART]

Процесс получения прошивки загрузчика состоит из предварительного конфигурирования Makefile, где настраиваются опции (если это необходимо) и последующей компиляции командами make clean и make. Конечно же, для компиляции у Вас должен быть установлен тулчейн (компилятор AVR GCC и библиотеки). На операционной системе Windows тулчейн можно получить, если установить пакет разработки WinAVR или Atmel Studio.

Когда нужно получить загрузчик для Arduino, то чаще всего (в зависимости от типа платы или Вашей конструкции) это микроконтроллер ATmega328, или реже ATmega168, ATmega8, ATmega32U4. Поэтому сначала нужно выбрать, какой загрузчик использовать. Почти все загрузчики можно найти в папке установки Arduino c:\Program Files\Arduino1.0.6\hardware\arduino\bootloaders, распределенные по подкаталогам atmega8, atmega и другим.

Выбор загрузчика. Если Вам нужен загрузчик для ATmega8, то его исходный код и Makefile находится в папке atmega8. Если нужен загрузчик для ATmega168 или ATmega328, то см. папку atmega. Если нужен загрузчик для ATmega32U4, то его можно найти в библиотеке LUFA, см. папку Bootloaders\DFU.

Примечание: исходный код и прошивки загрузчиков можно скачать по ссылке [9].

Конфигурирование загрузчика для ATmega8. Зайдите в папку atmega8, и откройте текстовым редактором файл Makefile. Вам нужно проверить следующие опции:

• DIRAVR. Эта опции указывают на каталог установки тулчейна (в этом каталоге находится папка bin с исполняемыми файлами для компилятора и других утилит, и папка include для заголовочных файлов библиотек). Если у Вас установлен тулчейн WinAVR, то значение этой опции должно быть наподобие c:\WinAVR-20100110\avr. Если у Вас установлен тулчейн в составе Atmel Studio, то значение этой опции должно быть наподобие "c:\Program Files\Atmel\AVR Tools\AVR Toolchain" (должны быть кавычки, потому что в составе пути есть пробелы).

• DEFS. В этой опции указана тактовая частота системы через значение макропеременной F_CPU. Например, если указана опция:

DEFS = -DF_CPU=8000000 -DBAUD_RATE=19200

то это означает, что прошивка будет скомпилирована в расчете на тактовую частоту 8 МГц. 8 МГц обычно используется, если работает внутренний RC-генератор микроконтроллера AVR. Если у Вас используется другая тактовая частота, задаваемая внешним кварцевым резонатором, то укажите рядом с -DF_CPU= тактовую частоту в Герцах. Чаще всего используется тактовая частота 16 МГц, т. е. нужно указать -DF_CPU=16000000.

Примечание: важно указать правильную тактовую частоту потому, что к этому значению привязана настройка последовательного порта UART, через который загрузчик получает код от хоста (из системы разработки Arduino IDE с помощью вызова утилиты программирования AVRDUDE). Неправильная настройка UART приведет к тому, что загрузчик не сможет получить код программы пользователя, и микроконтроллер не будет перепрошиваться через загрузчик.

На этом конфигурирование загрузчика можно считать законченным. Для получения прошивки загрузчика осталось выполнить последовательность из двух команд:

make clean
make hex

После компиляции получится файл ATmegaBOOT.hex, который можно с помощью программатора ISP записать в память микроконтроллера ATmega8. Не забудьте после программирования загрузчика правильно установить фьюзы микроконтроллера (см. таблицу 4).

Конфигурирование загрузчика для ATmega168 или ATmega328. Зайдите в папку atmega, и откройте текстовым редактором файл Makefile. Здесь все устроено несколько сложнее, потому что этот Makefile универсальный, он предназначен для получения прошивок для множества различных плат Arduino:

Таблица 8. Выбор цели (target) в Makefile для ATmegaXX8.

Плата Arduino Target
Arduino LilyPad lilypad
Arduino Pro или Arduino Pro Mini pro8, pro16 или pro20 в зависимости от используемой тактовой частоты
Arduino Diecimila diecimila
Arduino NG ng
Своя плата на ATmega328 atmega328
Arduino Pro на ATmega328P без кварца atmega328_pro8
Arduino Mega mega

Примечание: цель Target, указанная в таблице, подставляется как опция команды make при компиляции прошивки:

make clean
make < тут надо указать Target >

Первое, что Вам нужно сделать, это выбрать цель для компиляции (вариант из столбца Target таблицы 6) в зависимости от платы, которая у Вас используется. Предположим, что у Вас самодельная плата на микроконтроллере ATmega328, для которой Вы собираетесь сделать свой загрузчик. Тогда цель для компиляции у Вас будет atmega328, прошивка получается выполнением 2 команд:

make clean
make atmega328

Если у Вас используется другая тактовая частота, то проверьте значение макропеременной AVR_FREQ (по умолчанию для цели atmega328 задана тактовая частота 16 МГц: AVR_FREQ = 16000000L). После компиляции получите прошивку ATmegaBOOT_168_atmega328.hex, которую можно записать в память Вашего микроконтроллера с помощью программатора ISP. Внимание, не забудьте также правильно установить фьюзы микроконтроллера (см. таблицу 4).

[Ссылки]

1. AVR-USB-MEGA16: USB bootloader BootloadHID для микроконтроллера ATmega16.
2. AVR-USB-MEGA16: USB bootloader USBasp для микроконтроллера ATmega32.
3. Atmel AVR231: AES Bootloader.
4. Atmel AVR230: DES Bootloader.
5. Макетная плата AVR-USB162.
6. V-USB site:obdev.at.
7. USBtiny site:dicks.home.xs4all.nl.
8. USB bootloader Micronucleus.
9150117arduino-bootloaders.zip - исходный код и готовые прошивки загрузчиков Arduino. 

 

Комментарии  

 
0 #9 dimmer 18.09.2016 00:14
К вашему списку могу добавить бутлоадер, написанный для интерфейса RS-485. На сайте avr-assm.ru выложен исходник загрузчика на ассемблере и программа для компьютера.
Цитировать
 
 
0 #8 Владимир Хлуденьков 28.06.2016 11:19
Здравствуйте.
А из софта на стороне РС что посоветуете? avrdude?
Чтобы на него gui затем навесить.
По сценарию: заказчик подсоединил устройство, запустил программу обновления софта, нажал кнопку "ОК" и устройство прошилось?

microsin: да, avrdude лучше всего. Над ним оболочка есть, avrdude-gui. Если используете загрузчик USBasp, то также подойдут GUI-утилиты Khazama 1.6.2 и eXtreme Burner.
Цитировать
 
 
0 #7 Mixer 23.02.2015 17:34
Спасибо всем, кто делится информацией, особая благодарность энтузиастам, поддерживающим работу сайта! Если бы не ваша помощь, послал бы я заказчиков в долгий эротический путь, а теперь - подточил свои ASM-исходники и подсуну под Ардуинкину оболочку - ну хочет клиент, что бы было ему понятно где setup, а где главный цикл программы loop)
Цитировать
 
 
0 #6 Mixer 23.02.2015 17:16
Цитирую Kaseiiro:
И опять же, субъективно - bootloader для AVR НИ В КОЕМ СЛУЧАЕ НЕ НАДО ПИСАТЬ САМОСТОЯТЕЛЬНО, поскольку лучше, чем уже уже понаписано (причем столько, что не разгребете), Вы никогда не напишете.

Я, пожалуй, большей глупости, чем эта, еще не слыхивал... Пишу на чистом асме для AVR уже 10 лет (писал и TCP-UDP), и всегда стараюсь все писать свое - в этом и прелесть контроллера - за все можешь отвечать сам. И как же найти загрузчик с шифрованием прошивки, что бы передавать своим клиентам новые версии без возможности копипаста вашего устройства, а?

microsin: это Ваш выбор - тратить или нет собственные усилия на изобретение велосипеда. Ведь многие программируют не то чтобы для собственного удовольствия, как Вы, например, а просто тупо выполняют порученную работу, т. е. решают поставленную задачу максимально эффективно. А когда и стеки TCP, и и библиотеки для шифрования, и многое-многое другое - уже есть на блюдечке с голубой каемочкой - никто в здравом уме не решится тратить впустую драгоценное рабочее время.
Цитировать
 
 
0 #5 Дима 19.08.2011 18:58
Позарез нужен бутлоадер работающий на ATmega16, но по rs485 интерфейсу. То есть бутлоадер должен еще и дрыгать какой-нибудь ножкой микроконтроллер а, чтобы переключать драйвер max485 то на прием, то на передачу. Есть такой?

microsin: думаю, Вам нужно взять за основу бутлоадер для COM-порта (RS232, USART) и немножко его доработать, чтобы переключалось направление передачи данных. Бутлоадер RS232 для AVR найти не проблема.
Цитировать
 
 
0 #4 Дмитрий 11.07.2011 22:15
У меня вопрос по старту бута. Можно ли как-нибудь сделать, чтобы можно было обходится без перемычки? Т. е. чтобы просто подключил девайс к USB и сам USB хост сообщил ему, что надо стартануть бут? Например в основном коде придумать как ему сделать рестарт, а перед рестартом еще в ЕЕПРОм, например, флаг какой-нибудь установить, чтобы по рестарту он не выходил из бута, пока прошивку не всосет? Ну или как-то так?

microsin: вариантов решения проблемы запуска бутлоадера множество, и метод реализации запуска зависит целиком от Вашей фантазии. Просто придумайте, как Вы хотели бы, чтобы бутлоадер стартовал - и просто сделайте это, благо исходники бутлоадеров есть, и поменять их поведение достаточно просто. Стандартное решение - добавление в протокол обмена USB-устройства специальной команды, которая запускает бутлоадер. Тогда никакая перемычка не нужна.
Цитировать
 
 
+1 #3 Дима 30.12.2010 18:55
Есть ли бутлоадер для утилиты AVRprog, находящейся в составе AVRStudio?

microsin: к сожалению, такой бутлоадер пока не попадался. Если попадется, то обязательно будет его перевод или обзор. Теоретически такой бутлоадер можно реализовать самому, так как все основные части - протокол STK200 (или STK500) и класс CDC, реализованный на библиотеке V-USB, уже есть готовые в исходниках. Вот, кстати, хороший кандидат для переделки под V-USB - http://www.siwawi.arubi.uni-kl.de/avr_projects/index.html#avrprog_boot . Код хорошо документирован, и может быть легко портирован на V-USB. Основная проблема только в том, чтобы уместить получившийся код в секцию бутлоадера. Наверняка он влезет в boot-секцию только начиная с ATmega32.
Цитировать
 
 
0 #2 Kaseiiro 10.07.2010 15:43
Компилятору-то зачем знать про „меньше памяти“? Сами заметите. А загрузчику затирать себя можно и запретить.
И все же, субъективно: загрузчик лучше писать самостоятельно.

microsin: по поводу компилятора - Вы правы, если не задумываться от том, что НА САМОМ ДЕЛЕ хотели спросить. А в остальном... Все в этом мире с точки зрения человека субъективно. В том числе, с моей точки зрения - загрузчику лучше ничего не запрещать, а сделать его как можно тупее и меньше по размеру. И опять же, субъективно - bootloader для AVR НИ В КОЕМ СЛУЧАЕ НЕ НАДО ПИСАТЬ САМОСТОЯТЕЛЬНО, поскольку лучше, чем уже уже понаписано (причем столько, что не разгребете), Вы никогда не напишете.
Цитировать
 
 
0 #1 Маковюшка 07.07.2010 11:18
Огромное спасибо за содержание сайта - оно бесценно для электронщиков!

Подскажите пожалуйста, что нужно дописать, настроить в проекте WinAVR IAR CVAVR если программа создается под бутлодер? Т. е. как сообщить компилятору, что памяти доступно меньше, чем в выбранном камушке?

microsin: Вы указали целых три системы проектирования, поэтому для ответа на вопрос придется написать целую статью. Пожалуйста, задавайте конкретные вопросы, и еще лучше - пишите по этому поводу на на email. Объем памяти в общем случае задается в хедерах, описывающих микроконтроллер , или в настройках проекта, или в опциях линкера.
Цитировать
 

Добавить комментарий


Защитный код
Обновить

Top of Page