1. В сообществе нашего форума Вконтакте создан раздел по продаже электронных компонентов.
    Каждый может продать в нем свои залежавшиеся детали. Подробности здесь.

Туториал ChibiOS и STM32

Тема в разделе "ChibiOS/RTOS", создана пользователем radioengineer, 3 июн 2014.

  1. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Тема предназначена для глобального обсуждения аспектов разработки приложений под STM32, используя ОС реального времени ChibiOS. В первом топике буду вставлять нужные ссылки по теме, на документацию и т.д.

    Ссылки:
    http://www.chibios.org - официальный сайт ChibiOS
    Kernel and HAL Reference Manual - очень подробная документация с описанием ядра и уровня абстракции HAL на английском
    Форум поддержки - официальный форум, где разработчик отвечает на вопросы по ОС причем быстро.
    Блог PLAY Embedded - статьи, туториалы, видео уроки по ChibiOS

    Переводы и мануалы:
    Настройка проекта ChibiOS в Keil
    Компиляция проекта ChibiOS+uGFX в Cygwin
    Генерация board файлов для ChibiOS (ChibiOS Board Generator)
    Отладочная печать в COM порт (UART)
    Функция форматированного системного вывода chprintf()
    ChibiOS. Методика поиска и устранения неисправностей шины I²C на STM32
    ChibiOS. Как создавать потоки
    Концепция ядра ChibiOS / RT
    Схема HAL
    Драйвер PAL
    EXT Driver (драйвер EXT)
    Как портировать код с ChibiOS 2.x в ChibiOS 3.x
    Использование HAL GPT драйвера
    Регистры и битовые маски
    ChibiOS/HAL: объектно-ориентированный подход
    Библиотека для приемопередатчиков: nRF24L01 и ChibiOS/RT

    Туториалы на английском:
    Используем DHT11 с ChibiOS/RT
    АЦП и PWM на ChibiOS/RT

    FAQ
    Что делать если не работают функции из math.h?

    Интересные проекты:
    Осциллограф-мультиметр на STM32F4Discovery и ChibiOS/uGFX (туториал)
    Термометр на e-ink дисплее ED060SC4 (ChibiOS+uGFX)
    ChibiCube v2.0 (видео)
    MP3 плеер на STM32F4Discovery

    Вложения:
    ChibiDiscovery.rar - проект в Keil для платы STM32VLDiscovery (мигание светодиодом и кнопка)

    Вложения:

    Последнее редактирование: 19 авг 2017
     
    : rtos, chibios, stm32, keil, HAL, ugfx, осрв
  2. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Настройка проекта ChibiOS в Keil

    1. Заходим в настройки проекта:
    Скриншот 2014-06-03 13.48.17.png

    2. Вкладка Target, необходимо изменить опцию IRAM2. Здесь IRAM1 внутренняя RAM память МК равна 0x2000=8192 байта или 8кб. IRAM2 - это начало стека, явно устанавливается равным 1 байту. Стек используется для потоков ChibiOS.
    Скриншот 2014-06-03 13.45.26.png

    3. Вкладки Output, Listing и User в принципе не требуют изменения.

    4. Вкладка С/С++. Здесь в общем самые важные настройки: Поле Define заполняется строкой __heap_base__=Image$$RW_IRAM1$$ZI$$Limit __heap_end__=Image$$RW_IRAM2$$Base
    Скриншот 2014-06-03 14.10.14.png

    5. В Include Paths указываются пути до заголовочных файлов.
    Скриншот 2014-06-03 14.22.05.png

    6. Вкладка Asm тоже требует настройки. В поле Misc Controls прописываем --cpreproc
    Скриншот 2014-06-03 14.23.37.png

    7. Инклуды для Asm:
    Скриншот 2014-06-03 14.23.41.png

    8. Вкладка Linker не требует настройки. Debug и Utilities настраивается на использование ST-Link
  3. koteika

    koteika В доску свой

    Сообщения:
    768
    Симпатии:
    118
    Род занятий:
    программирование
    Перевел))) если есть какие не точности пишите..
    Концепция ядра ChibiOS / RT

    Соглашения об именах

    Имена оформляются в следующем виде:
    ch <group> <action> <suffix>()
    ch <группа> <действие> <суффикс>()

    например: chIQGetTimeoutS ()

    Возможны следующие группы: Sys, Sch, Time, VT, Thd, Sem, Mtx, Cond, Evt, Msg, Reg, SequentialStream, IO, IQ, OQ, Dbg, Core, Heap, Pool.

    Суффикс может быть одним из следующих:

    None , API, без каких-либо суффиксов, не могут быть вызваны из кода пользователя, если по-другому не указано. Смотреть состояния системы.

    "I", API, I-класса являются нерегулярными только в состояниях I-Locked или S-Locked. Смотреть состояния системы.

    "S", API S-класса являются нерегулярными только с S-Locked состоянии. Смотреть состояния системы.

    Примеры: chThdCreateStatic (), chSemSignalI (), chIQGetTimeout ().

    Классы прерываний

    В ChibiOS / RT существуют 3 класса прерываний:

    Regular Interrupts/Регулярные прерывания. Маскировка источников прерываний, которые не могут повлиять на код и таким образом появляется возможность ссылаться API операционной системы изнутри их обработчиков. Обработчики прерываний, принадлежащие к этому классу должны быть написаны с помощью определенных правил. См. группу интерфейсов API системы и веб-статьи, как написать обработчики прерываний.

    Fast Interrupts/Быстрые прерывания. Маскировка источников прерываний с возможностью повлиять на код ядра и таким образом имеют меньшую скрытность и менее подвержены дребезгу см. на веб-статью время отклика и дребезга. Такие источники поддерживаться не на всех архитектурах.

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

    Non Maskable Interrupts/Не маскируемые прерывания. НЕ маскируемые источники прерываний полностью не контролируются операционной системой и имеют наименьшую скрытность. Такие источники поддерживаться не на всех архитекторах.

    Состояния системы

    При использовании ChibiOS / RT система может находиться в одном из следующих рабочих состояний:

    Init. Когда система находится в этом состоянии все маскируемые источники прерываний отключены. В этом состоянии не представляется возможным использовать любые системы API, кроме chSysInit (). Это состояние возможно после физической сброса.

    Normal. Все прерывания источники включены, доступны API-интерфейсы , потоки выполняются.

    Suspended. В этом состоянии включены быстрые источники прерываний , регулярные источники прерываний отключены. В этом состоянии не представляется возможным использовать системой любых API, исключением являются chSysDisable () или chSysEnable (), для того чтобы с помощью них изменить состояние системы..

    Disabled. Когда система находится в этом состоянии, регулярные и быстрые источники прерываний отключены. В этом состоянии не представляется возможным использовать системой любых API, исключением являются chSysSuspend () или chSysEnable (), для того чтобы с помощью них изменить состояние системы.

    Sleep. Архитектурно-зависимый режим пониженного энергопотребления, в этом состоянии находятся простаивающие потоки и ждут(ожидают) прерывания. После обслуживания прерывания восстанавливается нормальное состояние.

    S-Locked. Ядро заблокировано и регулярные источники прерываний отключены. Быстрые источники прерываний включены. API-интерфейсы S-класса, и I-класса являются нерегулярными в этом состоянии.

    I-Locked. Ядро заблокировано и регулярные источники прерываний отключены. API-интерфейсы I-класса являются нерегулярными из этого состояния.

    Обслуживание регулярных прерываний. API не доступны, но можно переключиться на состояние I-Locked, используя chSysLockFromIsr (), а затем вызвать любой API I-Class. Обработчики прерываний могут быть вытесняемыми на некоторых архитектурах, для того чтобы перейти к I-Locked состоянию до вызова API.
    Обслуживание быстрых прерывание. Системные интерфейсы недоступны.
    Обслуживание не маскируемых прерываний. Системные интерфейсы недоступны.

    Halted. Все источники прерываний отключены и система переходит в бесконечный цикл. Это состояние может быть достигнуто, если режим отладки активируется и обнаруживается ошибка или после явно вызова функции chSysHalt ().

    На следующей диаграмме показаны возможные переходы между состояниями:

    рис 1.png
    рис 1.
    рис 2.png
    рис 2.

    * За исключением: Init, Halted, SNMI, неактивных.

    Очередность потоков

    Потоки которые готовы и имеют наивысший приоритет выполняется. Если 2 и более потоков имеют один и тот же приоритет то они выполняются циклически.
    рис 3.png
    рис 3.

    Состояния потоков

    Изображение показывает, как потоки могут изменить свое состояние в ChibiOS / RT.
    рис 4.png
    рис 4.

    Уровни приоритета

    IDLEPRIO
    , это самый низкий уровень приоритета и зарезервирован для простаивающего потока, другие потоки не должны занимать этот уровень приоритета.

    LOWPRIO, самый низкий уровень приоритета, который может быть назначен на пользовательской нити.

    NORMALPRIO, это центральный уровень приоритета для пользовательских нитей. Желательно, его назначить для потоков.

    HIGHPRIO, самый высокий уровень приоритета, который может быть назначен на пользовательской нити.

    ABSPRO, самый максимальный уровень приоритета.

    Рабочая зона

    Каждый поток имеет свой собственный стек, структуру и некоторые преимущественные зоны. Все структуры выделяются в рабочей области, поток в стеке, как правило в статически объявленном коде. Не используется память за пределами рабочей зоны, за исключением когда есть доступ к общим данным.

    рис 5.png
    рис 5.
    Последнее редактирование модератором: 4 июн 2014
  4. koteika

    koteika В доску свой

    Сообщения:
    768
    Симпатии:
    118
    Род занятий:
    программирование
    Схема HAL:
    group___i_o.png

    Подробное описание:

    Абстрактное представление аппаратных средств:

    ChibiOS / RT имеет множество различных интерфейсов называемых драйверами устройств. Подсистема HAL это абстрактное представление аппаратных средств.

    HAL является интерфейсом между ChibiOS / RT и железом.


    Архитектура драйверов устройств HAL:

    Драйвер устройства состоит из двух уровней:

    High Level Device Driver (HLD) - Драйвер высокого уровня устройства. Этот уровень содержит определения интерфейсов драйвера и платформы- самостоятельной части драйвера.

    HLD состоит из двух файлов:

    <driver>. с, файл реализации HLD. Этот файл должен быть включен в Makefile, для того чтобы можно было использовать драйвер.

    <driver>. h, файл заголовка HLD. Этот файл не явно включен в файле заголовка HAL hal.h.

    Low Level Device Driver (LLD) - Низкий уровень драйверов устройств. Этот уровень содержит платформо-зависимую часть драйвера.

    LLD состоит из двух файлов:

    <driver> _lld.c, файл реализации LLD. Этот файл должен быть включен в Makefile, для того чтобы можно было использовать драйвер.

    <driver> _lld.h, файл заголовка LLD. Этот файл неявно включен файл заголовка HLD.

    LLD может и не присутствовать в драйвере, который обращается к оборудованию напрямую, а может присутствовать в других драйверах устройств, как например драйвер MMC_SPI использует SPI и драйверы PAL в целях реализации своих функций.

    dot_inline_dotgraph_23.png
    Последнее редактирование модератором: 5 июн 2014
  5. koteika

    koteika В доску свой

    Сообщения:
    768
    Симпатии:
    118
    Род занятий:
    программирование
    Перевел не большой отрывок по PAL драйверу ChibiOS...

    Драйвер PAL

    Схема PAL Driver:
    group___p_a_l.png

    Подробное описание

    Абстрактные порты ввода / вывода:
    Этот модуль определяет абстрактный интерфейс для портов цифровых входов / выходов. Заметим, что большинство функций I / O портов это макросы.
    PAL драйвер имеет независимый доступ к портам ввода / вывода платформы и при этом может быть оптимизирован для конкретных архитектур.
    Обратите внимание, что драйвер PAL низкого уровня также может предложить нестандартные макросы и функции для создания специфических возможностей, но использование таких интерфейсов не будут переносимым. Такие интерфейсы должны быть записаны с именем архитектуры внутри имен функций.

    Условие:
    Для того чтобы использовать драйвер PAL должна быть включена опция HAL_USE_PAL в halconf.h.

    Описание функций, структур, макросов:

    Data Structures
    struct IOBus
    Дескриптор шины I/O.

    struct PALConfig
    Статическая инициализация I/O портов.

    Functions
    ioportmask_t
    palReadBus (IOBus *bus)
    Чтение I/O линии.

    void palWriteBus (IOBus *bus, ioportmask_t bits)
    Запись I/O линии.

    void palSetBusMode (IOBus *bus, iomode_t mode)
    Programs a bus with the specified mode.

    void _pal_lld_init (const PALConfig *config)
    Конфигурация STM32 I/O портов.

    void _pal_lld_setgroupmode (ioportid_t port, ioportmask_t mask, iomode_t mode)
    Настройка режима работы пина.

    Pads mode constants
    #define PAL_MODE_RESET 0
    Состояние после сброса.

    #define PAL_MODE_UNCONNECTED 1
    Безопасное состояние для не подключенного пина.

    #define PAL_MODE_INPUT 2
    Z состояние пина.

    #define PAL_MODE_INPUT_PULLUP 3
    Вход с подтяжкой.

    #define PAL_MODE_INPUT_PULLDOWN 4
    Вход без подтяжки.

    #define PAL_MODE_INPUT_ANALOG 5
    Аналоговый вход.

    #define PAL_MODE_OUTPUT_PUSHPULL 6
    Пин в режиме Push-pull выход.

    #define PAL_MODE_OUTPUT_OPENDRAIN 7
    Пин в режиме Open-drain выход.

    Logic level constants
    #define PAL_LOW 0
    Логическое состояние 0(низкое).

    #define PAL_HIGH 1
    Логическое состояние 1(единицы).

    Macro Functions

    #define palInit(config) pal_lld_init(config)
    Инициализация модуля PAL.

    #define palReadPort(port) ((void)(port), 0)
    Чтение состояние I/Oпорта.

    #define palReadLatch(port) ((void)(port), 0)
    Чтение выходного состояние порта.

    #define palWritePort(port, bits) ((void)(port), (void)(bits))
    Запись маски битов в I/Oпорт.

    #define palSetPort(port, bits) palWritePort(port, palReadLatch(port) | (bits))
    Установка маски битов в I/Oпорт.

    #define palClearPort(port, bits) palWritePort(port, palReadLatch(port) & ~(bits))
    Очистка маски битов в I/Oпорту.

    #define palTogglePort(port, bits) palWritePort(port, palReadLatch(port) ^ (bits))
    Переключение маски битов на I/Oпорт.

    #define palReadGroup(port, mask, offset) ((palReadPort(port) >> (offset)) & (mask))
    Считывание группы битов.

    #define palWriteGroup(port, mask, offset, bits)
    Запись группы битов.

    #define palSetGroupMode(port, mask, offset, mode)
    Настройка режима группы пинов.

    #define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1)
    Считывание логического состояния на выходном пине.

    #define palWritePad(port, pad, bit)
    Запись логического состояния в пин.

    #define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
    устанавливаетPAL_HIGH.

    #define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
    ОчищаетPAL_LOW.

    #define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
    Переключает логическое состояние пина.

    #define palSetPadMode(port, pad, mode) palSetGroupMode(port, PAL_PORT_BIT(pad), 0, mode)
    Установка рабочего состояния пина.

    ....продолжение следует
    Djoni_S нравится это.
  6. Djoni_S

    Djoni_S Гость

    Сообщения:
    1
    Симпатии:
    0
    Интересная операционка, когда ожидается продолжение.
  7. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Продолжение по мере изучения:) Последняя статья http://blog.radiotech.kz/blog/stm32/39.html выложена сегодня.
  8. koteika

    koteika В доску свой

    Сообщения:
    768
    Симпатии:
    118
    Род занятий:
    программирование
    EXT Driver (драйвер внешних прерываний)

    Схема EXT Driver:
    group___e_x_t.png
    Этот драйвер реализует управление внешними прерываниями в ChibiOS.

    Для того чтобы использовать драйвер EXT опция HAL_USE_EXT должна быть включена в файле halconf.h.

    Не все функциональные возможности драйвера можно использовать в любой момент, любой переход который не показан на следующем рисунке должен рассматриваться как ошибка:
    dot_inline_dotgraph_8.png
    Операции драйвера:
    Драйвер абстрагирует обратный вызов общих источников внешних прерываний, когда вызов обнаружен на одном из настроенных каналов. Возможны несколько режимов:

    EXT_CH_MODE_DISABLED, канал не используется.
    EXT_CH_MODE_RISING_EDGE, обратный вызов по переднему фронту.
    EXT_CH_MODE_FALLING_EDGE, обратный вызов по заднему фронту.
    EXT_CH_MODE_BOTH_EDGES, обратный вызов на обоих фронтах.

    Структуры драйвера:
    EXTChannelConfig -конфигурация каналов.
    EXTConfig - конфигурация драйвера.
    EXTDriver - структура представляющая собой драйвер EXT.

    Функции для работы с драйвером:
    extInit (void) - инициализация драйвера
    extObjectInit (EXTDriver *extp) - инициализация стандартной части структуры драйвера
    extStart (EXTDriver *extp, const EXTConfig *config) - настройка и активация EXT периферии драйвера
    extStop (EXTDriver *extp) - отключение EXT периферии
    extChannelEnable (EXTDriver *extp, expchannel_t channel) - включение канала прерываний
    extChannelDisable (EXTDriver *extp, expchannel_t channel) - отключение канала прерываний
    extSetChannelModeI (EXTDriver *extp, expchannel_t channel, const EXTChannelConfig *extcp) - изменение режима работы канала
    ext_lld_init (void) - низкий уровень драйвера
    ext_lld_start (EXTDriver *extp) - настройка и старт периферии драйвера
    ext_lld_stop (EXTDriver *extp) - остановка периферии драйвера
    ext_lld_channel_enable (EXTDriver *extp, expchannel_t channel) - включение канала
    ext_lld_channel_disable (EXTDriver *extp, expchannel_t channel) - отключение канала

    Переменные:
    EXTD1 - идентификатор драйвера EXT1

    Режимы EXT канала:
    EXT_CH_MODE_EDGES_MASK 3 - маска полей режима
    EXT_CH_MODE_DISABLED 0 - канал отключен
    EXT_CH_MODE_RISING_EDGE 1 - нарастающий фронт
    EXT_CH_MODE_FALLING_EDGE 2 -задний фронт
    EXT_CH_MODE_BOTH_EDGES 3 - оба поля по заднему фронту
    EXT_CH_MODE_AUTOSTART 4 -канал автоматически устанавливаемый при старте драйвера
    Последнее редактирование: 4 июл 2014
    Djoni_S и radioengineer нравится это.
  9. electrotehnik

    electrotehnik Гость

    Сообщения:
    7
    Симпатии:
    0
    Добавьте во вложения первого поста исходники проекта для платы HY-Mini STM32V, пожалуйста.
    Это довольно известная плата, думаю многим пригодятся и файлы board, и драйвера дисплея, и общая структура проекта в Eclipse и/или Keil для более наглядного представления.
    Последнее редактирование: 12 окт 2014
  10. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Создал отдельную тему для обсуждения.
  11. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    На официальном сайте добавили много новых мануалов по Chibios. Плюс вышла новая стабильная версия 2.6.7
  12. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
  13. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
  14. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Итак, добавлю небольшой лайфхак работы с математическими функциями в #chibios Сегодня писал небольшую программку для снятия данных с датчика магнитного поля и нарвался на интересную ошибку в процессе компиляции. При использовании функции из math.h angle = atan2(y, x) - вычисление арктангенса между двумя векторами, выпадала ошибка компилятора undefined reference to `atan2'. На официальном форуме #chibios нашел решение: добавляем в Makefile в опции компилятора USE_OPT опцию -lm для поиска в процессе сборки math.h
  15. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Отладочная печать в COM порт (UART)

    Немного коснемся отладки в #chibios. Итак, я довольно давно и успешно пользуюсь отладочной печатью в консоль на разных своих проектах. Те, кто программирует для #arduino хорошо знакомы с Serial Monitor, вот про такую штуку и речь. Для #chibios тоже есть возможность эффективно использовать подобный функционал. Я буду рассматривать материал на основе платы STM32F4DISCOVERY.
    1. Сперва нужно добавить поддержку SERIAL в halconf.h:
    Код:
    #define HAL_USE_SERIAL              TRUE
    В том же файле задаем скорость обмена по умолчанию:
    Код:
    #define SERIAL_DEFAULT_BITRATE  115200
    2. Добавляем в блок CSRC Makefile компиляцию файла chprintf.c
    Код:
    $(CHIBIOS)/os/various/chprintf.c
    3. Используем следующим образом, в своей программе добавляем заголовочный файл
    Код:
    #include <chprintf.h>
    В main() запускаем serial и настраиваем выводы на альтернативные функции (я использую USART2):
    Код:
    sdStart(&SD2, NULL);
    palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
    palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
    Далее в нужных местах просто вставляем вызов отладочной функции:
    Код:
    chprintf((BaseSequentialStream *) &SD2, "UART Init! Great!");
    4. И готово! Для линуксоидов: для отладки использую терминал CuteCom.
    Последнее редактирование: 26 фев 2015
  16. Sergey

    Sergey В доску свой

    Сообщения:
    46
    Симпатии:
    12
    Хорошо бы еще пример вывода строк + десятичные/16-тиричные значения
  17. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Это обычный форматированный вывод printf() и используется аналогично. Сделаю сегодня небольшую статейку по этой функции #chibios
  18. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    Итак, как обещал, небольшой мануал по chprintf().
    Код:
    void chvprintf ( BaseSequentialStream *  chp,
                      const char *  fmt,
                      va_list  ap
                   )  
    Функция форматированного системного вывода включает в себя минимальную функциональность vprintf() с выводом в поток BaseSequentialStream. Основные параметры форматирования следующие:
    Параметр "p" поддерживает следующие типы:
    • x hexadecimal integer.
    • X hexadecimal long.
    • o octal integer.
    • O octal long.
    • d decimal signed integer.
    • D decimal signed long.
    • u decimal unsigned integer.
    • U decimal unsigned long.
    • c character.
    • s string.
    Не стал переводить имена типов, думаю так всем понятнее. Функция принимает на вход следующие параметры:
    Поддержка чисел с плавающей точкой задается в chprintf.h
    Код:
    #define CHPRINTF_USE_FLOAT FALSE
    Пример вывода:
    Код:
    chprintf((BaseSequentialStream *) &SD2, "Number of bytes is %u", numBytes);
  19. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    koteika нравится это.
  20. radioengineer

    radioengineer Администратор Команда форума

    Сообщения:
    3.582
    Симпатии:
    355
    Адрес:
    Алматы
    koteika нравится это.

Поделиться этой страницей