Easyelectronics.ru

Электроника для всех
Текущее время: 20 сен 2020, 03:11

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 407 ]  На страницу Пред.  1 ... 4, 5, 6, 7, 8, 9, 10 ... 17  След.
Автор Сообщение
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 04 сен 2017, 21:40 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
Спасибо, попробую обычную Си функцию описать


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 13:27 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
столкнулся с пока не разрешимой для себя проблемой

пишу шаблонный класс таймера который будет раскрываться с вектором внешних функций который он должен вызывать с заданной периодичностью
и второй параметр шаблона - железный драйвер конкретного таймера на конкретном железе (avr8/stm8/stm32)

сейчас под avr8 написал статический обработчик ISR() в котором вызывается функция по адресу из статической переменной с указателем

и план был внутри инициализации класса таймера инициализировать этот указатель на статическую функцию класса
но возникла проблема с данными, как быть?
статические данные не находит линковщик
если я делаю обычные поля и определяю в вызывающей программе экземпляр класса то я не могу инициализировать статический указатель для вызовы из ISR

возможно сам подход надо поменять, но как?

задача - иметь возможность просто определить таймер с железныйм драйвером и указать какой вектор вызывать


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 13:47 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
сейчас под avr8 написал статический обработчик ISR() в котором вызывается функция по адресу из статической переменной с указателем

и план был внутри инициализации класса таймера инициализировать этот указатель на статическую функцию класса
но возникла проблема с данными, как быть?
статические данные не находит линковщик
если я делаю обычные поля и определяю в вызывающей программе экземпляр класса то я не могу инициализировать статический указатель для вызовы из ISR

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 13:54 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
у меня сходу не получилось повторить, это из за шаблонов и их параметров
но я сейчас нашел такое решение, просьба оценить:

- сделал структуру данных my_data
- сделал класс A_Data в котором вставил эту структуру как статическое поле (структуру использовал для простоты описания)
- объявил статические данные класса my_data A_data::data;
- сделал шаблог A c наследованием от A_Data

теперь соотвественно статические методы раскрытого шаблона работают со статическими данными и можно делать статический референс для ISR()
но есть одно но
если раскрыть два шаблона с разными параматерами (например с драйверами Timer0 и Timer1) то они будут работать не правильно, так как будут ссылаться на одни и теже данные

в данной задаче два таймера врядли потребуются в одной программе, но вот в другой задаче такое ограничение может стать проблеммой
есть решение?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 14:03 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
cам спросил сам отвечаю)

убрал класс A_Data и сделал объявление данных в самом шаблоне с параметрами шаблона

Код:
      template <typename TimerDriver, typename Vector>
      class Freq10 {
      protected:
         static freq10_data data;
         static void handler(void);
      };

      template <typename TimerDriver, typename Vector>
      freq10_data Freq10<TimerDriver, Vector>::data;

      template <typename TimerDriver, typename Vector>
      void Freq10<TimerDriver, Vector>::handler(void) {
         data.precount = 0;
      }


кстати, я правильно вынес код handler из описания класса? код будет довольно большой и внутри класса его сложно воспринимать


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 16:31 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
кстати, я правильно вынес код handler из описания класса? код будет довольно большой и внутри класса его сложно воспринимать

Вынес бы неправильно, наверно бы и не компилировалось...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 16:46 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
ну одно дело компилируется, а другое - ведет себя так как думается

по поводу объявления статических данных шаблона
я правильно понимаю, что шаблон раскрытый с разными параметрами создаст разные набор статических данных?
т.е. в примере выше поле data для раскрытых шаблонов для TimerDriver=Timer0 и Timer1 будут разные, так?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 16:55 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
я правильно понимаю, что шаблон раскрытый с разными параметрами создаст разные набор статических данных?
т.е. в примере выше поле data для раскрытых шаблонов для TimerDriver=Timer0 и Timer1 будут разные, так?

Да, причем подобные вещи можно за несколько минут проверить самому :)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 17:05 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
до проверок и изучения листингов пока не добрался)
однако прошивка по размеру сравнялась с сишной, что радует при том что использование прекомпилятора сведено в минимум
а гибкость увеличилась заметно

еще вопрос - а как то можно пропускать указание части параметров шаблона и соотвественно как то это внутри шаблона отражать?
например вместо трех указателей на функции передать две, а третью соотвественно в runtime надо исключить из вызова

черновой вариант у меня - объявил пустую функцию и ее адрес присвоил как значение по умолчанию
но при это таки адрес передается и функция вызывается и как минимум сколько то байт памяти тратится


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 18:02 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
еще вопрос - а как то можно пропускать указание части параметров шаблона и соотвественно как то это внутри шаблона отражать?
например вместо трех указателей на функции передать две, а третью соотвественно в runtime надо исключить из вызова

черновой вариант у меня - объявил пустую функцию и ее адрес присвоил как значение по умолчанию
но при это таки адрес передается и функция вызывается и как минимум сколько то байт памяти тратится

Если указателю на функцию присваивать указатель на пустую функцию, то естественно вызов никуда не денется... Попробуй присвоить по умолчанию nullptr и перед вызовом делать проверку, тогда оптимизатор сможет этот вызов выкинуть. Естественно это для случая когда эти указатели ни в каких переменных промежуточно не хранятся.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 18:14 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
на nullptr ругается:

Цитата:
identifier 'nullptr' is a keyword in C++11 [-Wc++0x-compat]


и не факт что это отработает в IAR/STM8 и Keil/STM32

по идее если я буду проверять на равенство ссылке на мою пустую функцию то оптимизатор должен удалить как и кусок кода с вызовом, а может и саму функцию?

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

есть два варианта:
1) под каждый конкретный ISR использовать глобальный экземпляр этого типа, тогда я буду иметь под каждый ISR свою переменную для хранения указателя на функцию для вызова
2) сделать шаблон со статичными данными и функциями и под каждый ISR делать свое раскрытие шаблона

какой вариант предпочтительней?
и как сделать независимые раскрытия шаблона при том, что там по логике не нужны никакие параметры?
в голову приходит что то типа такого:

Код:
template <int a>
class D {
}

typedef D<0> isr0;
tyepdef D<1> isr1;


где число в качестве параметра шаблона фейковое, нигде в шаблоне не участвует и используется только для получения индивидуальных типов


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 18:57 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
на nullptr ругается:

и не факт что это отработает в IAR/STM8 и Keil/STM32

по идее если я буду проверять на равенство ссылке на мою пустую функцию то оптимизатор должен удалить как и кусок кода с вызовом, а может и саму функцию?

Не так важно nullptr, NULL или 0, компилятор выкинет, или будет пытаться выкинуть, вызов функции если условие будет ложно. Проще и логичнее делать вызов если значение указателя не нулевое, но если сильно хочется можно проверять и на неравенство указателю на пустую функцию :)

Цитата:
еще вопрос, пишу несколько ISR в каждом получается однотипный статичный класс на который я потом ссылаюсь из конкретного ISR
по сути классы полностью одинаковые

есть два варианта:
1) под каждый конкретный ISR использовать глобальный экземпляр этого типа, тогда я буду иметь под каждый ISR свою переменную для хранения указателя на функцию для вызова
2) сделать шаблон со статичными данными и функциями и под каждый ISR делать свое раскрытие шаблона

какой вариант предпочтительней?

Это уже на твое усмотрение. У меня подобная проблема была с инициализацией GPIO для STM32, там можно было в месте инициализации напрямую вставлять нужный код, который может быть не таким и маленьким если выполнять инициализацию по всем правилам, или можно обойтись более медленным вызовом функции, что на достаточно большом числе вызовов обернется уменьшением размера бинарника...

Цитата:
и как сделать независимые раскрытия шаблона при том, что там по логике не нужны никакие параметры?

Опять же не совсем понятно зачем это делать? Чтобы получить уникальные статические поля? Может проще не делать их статическими?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:01 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 2471
axill писал(а):
и не факт что это отработает в IAR/STM8 и Keil/STM32

А нафига они нужны? Особенно второй.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:05 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 2471
Reflector писал(а):
У меня подобная проблема была с инициализацией GPIO для STM32, там можно было в месте инициализации напрямую вставлять нужный код, который может быть не таким и маленьким если выполнять инициализацию по всем правилам, или можно обойтись более медленным вызовом функции, что на достаточно большом числе вызовов обернется уменьшением размера бинарника...

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:18 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
Reflector писал(а):
Опять же не совсем понятно зачем это делать? Чтобы получить уникальные статические поля? Может проще не делать их статическими?

чтобы избежать вызова не статических функций, если правильно понимаю то нестатическая функция имеет +1 скрытый аргумент со ссылкой на данные экземпляра

сделал с шаблонами, но пока не проверял, надо убедиться, что данные не пересекаются

так и не придумал более удачного способа как совместить шаблон и ISR
шаблон раскрывается в пользовательской программе, а ISR определен в библиотеке
в идеале бы чтобы в ISR вставлялся статический метод раскрытого шаблона, но это как я вижу можно сделать только в пользовательской программе, что нарушает целостность библиотеки
пока оставил так, что в библиотеке ISR вызывает функцию по указателю из RAM, в этот указатель заполняется ссылкой на нужный статический метод раскрытого шаблоно в runtime

кстати NULL не возможно передать в качестве значения параметра типа ссылка на функцию, копилятор ругается, что обычное число для этой цели не катит


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:19 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
evsi писал(а):
А нафига они нужны? Особенно второй.

есть 1001 задача для которых даже этого много


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:29 
Старожил
Аватара пользователя

Зарегистрирован: 23 сен 2012, 20:35
Сообщения: 2471
axill писал(а):
evsi писал(а):
А нафига они нужны? Особенно второй.

есть 1001 задача для которых даже этого много

Именно. Достаточно поддержать компиляторы, которые в состоянии прожевать такой код. Кто не в состоянии - в сад. Вместе с фанатами.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 19:37 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
evsi писал(а):
Именно. Достаточно поддержать компиляторы, которые в состоянии прожевать такой код. Кто не в состоянии - в сад. Вместе с фанатами.


все жуют

а так ваш вопрос можно довести до абсурда, например так - зачем на дорогах жигули?
достаточно допускать на дороги те авто, которы в состоянии при пережовывании выдавать не хуже ЕВРО5
как то так...
извечный срачь

тема не об этом


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 21:03 
Только пришел

Зарегистрирован: 04 сен 2017, 22:09
Сообщения: 6
axill писал(а):
есть в Си такой кусок кода инициализации таймера ... как это красиво сделать с шаблонами?

Стормозил немного, но есть следующий вариант: пусть if выполняемый на стадии компиляции появился только в С++17, но разрешен тернарный оператор. Мой вариант реализации следующий:
Код:
#ifndef F_CPU
#define F_CPU 8000000UL
#endif

#include <stdint.h>

typedef enum FCPU_Class {
   Low = F_CPU/8/256/10,
   High = F_CPU/64/256/10,
   Unsupported
} FCPU_Class;

struct GetFCPU_Class {
   static const FCPU_Class Value = (F_CPU >= 300000 && F_CPU <= 5000000) ? Low
         : (F_CPU > 5000000 && F_CPU < 16000000) ? High
         : Unsupported;
};

template<FCPU_Class T>
uint8_t _stavr_timer0_freq10_platform_init();

template<>
uint8_t _stavr_timer0_freq10_platform_init<Low>()
{
   TCCR0B = (0 << CS02) | (1 << CS01) | (0 << CS00);
   return GetFCPU_Class::Value;
}

template<>
uint8_t _stavr_timer0_freq10_platform_init<High>()
{
   TCCR0B = (0 << CS02) | (1 << CS01) | (1 << CS00);
   return GetFCPU_Class::Value;
}


Использовать так:
Код:
_stavr_timer0_freq10_platform_init<GetFCPU_Class::Value>();


Есть у меня подозрения, что можно написать и покрасивее) Шаблон функции имеет специализации только для значений FCPU_Class::Low и High, так что при попытке передачи левого значения или FCPU_Class::Unsupported произойдет ошибка линковки. Более информативно конечно сделать static_assert (есть в с++11, или же сгородить самостоятельно). Что-то вроде:

Код:
static_assert(GetFCPU_Class::Value == Unsupported, "Unsupported value of F_CPU");


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 21:14 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
Phyzic С трудом пока в такие выкрутасы вьезжаю)
Понял только что каким то образом комиилятору дали понять что раскрытие шаблона возможно лишь с двумя значениями и под каждое значение свой код
Так?

У меня по логике диапазоны, не совсем подходит, но учту
Спасибо


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 21:31 
Здравствуйте!

Зарегистрирован: 19 июн 2017, 21:11
Сообщения: 3
Тоже занимался подобным вопросом (оформление прерываний в C++), пришёл к такому решению:
для микроконтроллера определяем классы с прерываниями:
Код:
template < class IRQ >
class IRQ_Timer1_CompareA
{
    #pragma vector = 0x08
    static __interrupt void execute(void)
    {
        IRQ::execute();
    }
};

а код самого прерывания описывается в другом классе
Код:
struct IRQ_1ms
{
    #pragma inline = forced
    static inline void execute(void)
    {
        Counter_1s::Tick();
    }
};

связывание производится следующим образом:
Код:
template void IRQ_Timer0_CompareA < IRQ_1ms > ::execute();


что у меня в итоге получилось можно посмотреть здесь
viewtopic.php?f=16&t=32335


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 21:47 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
dm37 Посмотрю, спасибо

С avr-gcc так сеорее всего не получится, по другому векторы описываются, у меня не получается вектором сделать метод класса


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 21:56 
Старожил

Зарегистрирован: 23 янв 2016, 15:37
Сообщения: 1265
axill писал(а):
чтобы избежать вызова не статических функций, если правильно понимаю то нестатическая функция имеет +1 скрытый аргумент со ссылкой на данные экземпляра

Как бы да, есть this, а у виртуальных функций есть vtable, только не обязательно после оптимизации это все будет задействованно, особенно в простых классах. Функции же на стеке не хранятся, они лежат во флеше и компилятор обычно знает где именно, потому ему не нужно вызывать эти функции через this.

Цитата:
кстати NULL не возможно передать в качестве значения параметра типа ссылка на функцию, копилятор ругается, что обычное число для этой цели не катит

Число не подходит, приведи его к такому типу, который подойдет.

Phyzic писал(а):
Стормозил немного, но есть следующий вариант: пусть if выполняемый на стадии компиляции появился только в С++17, но разрешен тернарный оператор.

Этот тернарный оператор является аналогом простого if, речь шла совершенно о другом.

axill писал(а):
С avr-gcc так сеорее всего не получится, по другому векторы описываются, у меня не получается вектором сделать метод класса

C gcc для ARM такое не работает, но адрес вектора берется из таблицы, таблица во флеше или в RAM, в последнем случае меняй обработчики как угодно, но если таблица во флеше, то в нее тоже можно добавлять статические методы классов. Я пробовал оба подхода, но так практически никто не делает, нужно править стартап, а у большинства он до сих пор на ассме...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 22:07 
Только пришел

Зарегистрирован: 04 сен 2017, 22:09
Сообщения: 6
axill писал(а):
С трудом пока в такие выкрутасы вьезжаю)

Ничего сложного совершенно. Сверху вниз:
Объявляем перечисляемый тип FCPU_Class с тремя значениями, чтобы позже эти значения использовать для выбора между реализациями функции.
Код:
typedef enum FCPU_Class {
   Low = F_CPU/8/256/10,
   High = F_CPU/64/256/10,
   Unsupported
} FCPU_Class;

Кстати говоря, заметьте, что значения Low и High вычисляются на этапе компиляции. Также на этапе компиляции вычисляется и значение поля Value в структуре GetFCPU_Class, так как в качестве исходных данных используются константы, известные компилятору. Вообще, при компиляции можно вычислить что угодно)
Дальше, говорим компилятору, что существует такая функция:
Код:
template<FCPU_Class T>
uint8_t _stavr_timer0_freq10_platform_init();

Но тела у этой функции нет. Компилятор это устраивает, пока никто эту функцию не использует.
Далее приводятся две специализации этой функции - для Low и High. Их использовать теперь можно - у них есть тело, но у всех остальных возможных значений - нет.
А дальше просто функция вызывается с параметром шаблона, который вычисляется при компиляции. Если в результате вычисления получится Low или High - все норм, вызывается одна из них. Иначе компилятор просто не видит возможной подстановки и матерится.
Вообще говоря, отлично рассказывает про использование плюсов в МК neiver, поищите его статьи на ресурсе. И еще, нашел отличный материал об использовании с++ в МК - какие фишки языка самые "дорогие" для использования, как избежать раздувания размера бинарника, как использовать шаблоны: http://caxapa.ru/thumbs/717646/effectcppemb.pdf


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Унифицированная кросс-платформенная библиотека Си
СообщениеДобавлено: 05 сен 2017, 22:11 
Только пришел

Зарегистрирован: 04 сен 2017, 22:09
Сообщения: 6
Reflector писал(а):
Этот тернарный оператор является аналогом простого if, речь шла совершенно о другом.

Эм, вроде вся фишка в том, что в constexpr-функциях в с++11/14 разрешено использование только return-выражения и простых операций, к которым относится всякая математика и тернарный оператор, а в с++17 уже можно городить полноценные constexpr-функции с if-ами и (вроде) циклами. А если речь про if при компиляции, то есть std::conditional и std::enable_if.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 407 ]  На страницу Пред.  1 ... 4, 5, 6, 7, 8, 9, 10 ... 17  След.


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB