Easyelectronics.ru

Электроника для всех
Текущее время: 26 май 2019, 21:10

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



JLCPCB – Прототипы печатных плат за $2/10pcs (Любой цвет!)
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 18 ] 
Автор Сообщение
 Заголовок сообщения: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 12:14 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Всем добра! Вообщем, перехожу сразу к проблеме.
Есть микроконтроллер с ядром Cortex-M3, и есть некоторая операция, которую он должен быстро-быстро делать.
Эти операции на Си выглядят так:
есть структура такого вида
Код:
typedef struct
{
  unsigned short int value_h;
  unsigned short int value_m;
  unsigned short int value_l;
} point_s;

есть кучка массивов, примерно таких
Код:
const uint16_t points_count  = 3; /** на самом деле элементов существенно больше, чем 3*/
const point_s array1[] =
{
  { 0x31C7, 0x1C75, 0x4CE9 },  { 0x31C7, 0x1CBB, 0x39FF },  { 0x31C7, 0x1C75, 0xD36B }
};

const point_s array2[] =
{
  { 0x31C7, 0x1C71, 0xC71C },  { 0x31C7, 0x1C60, 0x2673 },  { 0x31C7, 0x1C4B, 0x5EF9 }
};

const point_s array3[] =
{
  { 0x31C7, 0x1C75, 0x4CE9 },  { 0x31C7, 0x1CBB, 0x39FF },  { 0x31C7, 0x1C75, 0xD36B }
};

const point_s array4[] =
{
  { 0x31C7, 0x1C71, 0xC71C },  { 0x31C7, 0x1C60, 0x2673 },  { 0x31C7, 0x1C4B, 0x5EF9 }
};

const point_s array5[] =
{
  { 0x31C7, 0x1C75, 0x4CE9 },  { 0x31C7, 0x1CBB, 0x39FF },  { 0x31C7, 0x1C75, 0xD36B }
};

const point_s array6[] =
{
  { 0x31C7, 0x1C71, 0xC71C },  { 0x31C7, 0x1C60, 0x2673 },  { 0x31C7, 0x1C4B, 0x5EF9 }
};

const point_s array7[] =
{
  { 0x31C7, 0x1C75, 0x4CE9 },  { 0x31C7, 0x1CBB, 0x39FF },  { 0x31C7, 0x1C75, 0xD36B }
};

длиною points_count

на Си реализован цикл, которые перебирает все эти структуры и закидывает их в параллельную шину.
Код:
#define ADDR               (*(volatile uint16_t *)0x50000000) /** это 16-разрядная параллельная шина */
#define DATA               (*(volatile uint16_t *)0x50000002)

***
const point_s* fm;
/** и выбираю один из массивов, установив указатель на его первый элемент */
fm = &array3[0]; /** допустим, выбран массив array3*/
***
/** и перебираю его */
for (i = 0; i < points_count; i++)
{
  address = ((address == 0x1440) ? 0x1460 : 0x1440);
  port_status = (port_status == 1) ? 0 : 1;

  ADDR = address;
  DATA = fm->value_h;

  DDS_ADDR = address + 0x1;
  DDS_DATA = fm->value_m;

  DDS_ADDR = address + 0x2;
  DDS_DATA = fm->value_l;

  PORTB_PIN7 = port_status;
  fm++;
}

Всё это дело переписываю на ассемблер (на ассемблер переписываю только цикл for, остальное не так критично к быстродействию), и почти всё получилось, кроме пары моментов.
Собственно сами эти неполучившиеся моменты. Что-то неправильно читает данные с массива. Конечно описание проблемы просто шик, сейчас опишу что именно хочу узнать:)
После того, как определился, какой массив писать, я ставлю указатель на его первый элемент
Код:
const uint16_t* point_address;
point_address = &fm;

Show всё выглядит так

и в ассемблерной функции экспортирую эту переменную в регистр R2
Код:
  ldr   r2,  =point_address
  mov   r7,  #0
  ldr   r7,  [r2, #0]
  mov   r2,  r7

у меня теперь в регистре R2, как я понял, значение первой точки массива
Вот кусочек проблемного кода..
Код:
  .equ ADDR,           0x50000000 ;;также параллельная шина
  .equ DATA,           0x50000002
***
.extern points_count
.extern point_address
***
начинается функция
  .thumb
  load_points:

  ldr   r1,  =points_count
  mov   r7,  #0
  ldrh  r7,  [r1,  #0]
  mov   r1,  r7                ;;теперь в регистре R1 записано количество точек в массиве

  ldr   r2,  =point_address
  mov   r7,  #0
  ldr   r7,  [r2, #0]
  mov   r2,  r7                 ;; аналогично поступаю и с указателем на текущий элемент

  ldrh  r5,  [r2]   ;; тут в R5 записываю значение, которое по адресу, который хранится в R2, это, как понимаю, первый элемент структуры

loop_load_points: ;; это цикл, который пишет все элементы в параллельную шину
  movw  r8,  #0x1440 ;;сюда запишется fm->value_h
  movw  r9,  #0x1441 ;;сюда fm->value_m
  movw  r10, #0x1442 ;;сюда fm->value_l

  strh  r8,  [r3] ;; записываю адрес в параллельную шину
  strh  r5,  [r4] ;; записываю данные в параллельную шину

  ldrh  r5,  [r2, #2] ;; перехожу к следующему элементу структуры, т.к. uint16_t это 2 байта, то и смещение у меня #2

  strh  r9,  [r3] ;; аналогично вышестоящей записи
  strh  r5,  [r4]

  ldrh  r5,  [r2, #2] ;; перехожу к следующему элементу структуры

  strh  r10, [r3] ;; аналогично вышестоящей записи
  strh  r5,  [r4]

  ldrh  r5,  [r2, #2] ;; перехожу к следующему элементу структуры (думаю, это аналогично такой записи на Си *R5++)

  sub   r1,  r1,   #1  ;; points_count--
  cmp   r1,  #0  ;; if (r1 > 0)
  bgt   load_fm1_points ;; конец цикла

с массива читается всякая чушь..

Собственно, главный вопрос: как мне сделать инкремент сишного указателя?
Запись такого вида
Код:
ldrh  r5,  [r2, #2]

соответствует такой сишной записи?
Код:
r5 = *r2++

и перезапишет ли LDRH значение в R2?

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 12:59 
Старожил

Зарегистрирован: 13 фев 2011, 01:25
Сообщения: 616
Откуда: Севастополь
Цитата:
movw r8, #0x1440 ;;сюда запишется fm->value_h
movw r9, #0x1441 ;;сюда fm->value_m
movw r10, #0x1442 ;;сюда fm->value_l

А откуда собственно уверенность что запишется именно туда ? это адреса будут всегда разными при каждом изменении количества или размерности переменных. И вообще если честно - не увидел я деклараци указателей на массивы(для работы с ними из ассемблера). Тут нет ни чистого ассемблера ни чистого С а для смеси и того и другого - нужно все указатели прописывать в аргументах. Иначе будет каша. И глобальные переменные - зло великое есть.

по поводу последних строк вашего кода - запись ldrh r5, [r2, #2] означает - взять 16 битное значение из ячейки указатель на которую находится в регистре R2 со смещением +2 и положить взятое значение в регистр R5.
конструкция r5 = *r2++ будет записана в виде 2х строк
LDRH R5,[R2,#0]
ADD R2,R2,#2
Это для случая что работаете с вордом (16 бит). Мнемонику сложения точно не помню - возможно правильно она пишется как ADDI ( просто у разных компиляторов свои требования к записи мнемоник).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 13:52 
Старожил

Зарегистрирован: 10 июн 2011, 23:01
Сообщения: 3193
что именно по вашему компилятор в этом цикле делает не так, что надо это "оптимизировать"?
листинг компилятора покажите.

единственное что там можно "улучшить" в том виде как оно есть это пару тактов сэкономить на address ^= 0x20; если компилятор сам не догадался.

куда сильнее быстродействие может зависеть от того где данные и код лежат, в ram или flash.
и вообще для максимального быстродействия данные DMA должно перекладывать, а не процессор.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 16:16 
Старожил

Зарегистрирован: 30 апр 2010, 22:56
Сообщения: 1578
Откуда: Киев
Когда я увидел инструкцию If-then
и код типа
Код:
ITTE   NE        ; IT can be omitted
ANDNE  r0,r0,r1  ; 16-bit AND, not ANDS
ADDSNE r2,r2,#1  ; 32-bit ADDS (16-bit ADDS does not set flags in IT block)
MOVEQ  r2,r3     ; 16-bit MOV


я понял, что в голове я такое не уложу никак. Нехай компилятор этим занимается. Особенно в свете кэшей и конвееров.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 16:48 
Старожил

Зарегистрирован: 31 янв 2011, 19:17
Сообщения: 431
Откуда: Москва
_pv писал(а):
и вообще для максимального быстродействия данные DMA должно перекладывать, а не процессор.

А вот и нет. Сейчас не могу найти ссылку на пруф, но 1 транзакция dma исполняется за примерно 12 тактов. И какой-то чел писал в блоге, что сравнивал скорость и что DMA работает намного медленнее, чем процессором гонять. Ссылки постараюсь найти


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 29 апр 2015, 22:04 
Старожил

Зарегистрирован: 27 мар 2015, 01:22
Сообщения: 1353
Alisa писал(а):
Собственно, главный вопрос: как мне сделать инкремент сишного указателя?
Запись такого вида
Код:
ldrh  r5,  [r2, #2]

соответствует такой сишной записи?
Код:
r5 = *r2++

и перезапишет ли LDRH значение в R2?

Вот так будет соответствовать
ldrh r5, [r2], 2
И по новой моде - syntax unified - решётки можно не ставить )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 01 май 2015, 03:32 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Спасибо, господа, я разобрался с некорректным чтением из массива, теперь всё ок, грузится то, что надо
Но есть другой вопрос, с которым очень хочу разобраться.
Вот код, который работает, но немного некорректно.
Суть проста. Есть два комплекта адресов, в которые по очереди, чередуя записываю значения из массива
в регистрах R8, R9, R10 у меня адреса (чередую 0x1440, 0x1441, 0x1442 и 0x1460, 0x1461, 0x1462)
в R1 количество точек в массиве
в R3 адрес параллельной шины
в R4 данные параллельной шины
в R5 адрес ячейки, в которой нужная цифра (целый uint16_t, 2 байта)
в R7 уже считанное значение из этой ячейки (из адреса, который в R5)
в R11 адрес нужной ноги (тут через bit-band)
в R12 нужное значение порта (0 или 1)
Код:
  movw  r8,  0x1440
  movw  r9,  0x1441
  movw  r10, 0x1442

  ldr   r3,  0x50000000 ;;ADDR
  ldr   r4,  0x50000002 ;;DATA

;; цикл, к которому и относятся все мои вопросы:)
load_fm_points:
  eor   r8,  r8,    #20 ;; меняю адрес
  eor   r9,  r9,    #20
  eor   r10, r10,   #20

;; записываю нужные цифры во все три ячейки
  ldrh  r7,  [r5],  #2 ;; пост-инкремент адреса
  strh  r8,  [r3] ;;
  strh  r7,  [r4]

  ldrh  r7,  [r5],  #2
  strh  r9,  [r3]
  strh  r7,  [r4]

  ldrh  r7,  [r5],  #2
  strh  r10, [r3]
  strh  r7,  [r4]

;; тут инвертирую значение порта
  eor   r12, r12,  #1             @@ xor
  str   r12, [r11]                @@ write to register R11 (R11 - bit-band region PB7)

;; уменьшаю счётчик
  subs  r1,  r1,   #1             @@ points_count-- (r1 = points_count, result in r1)
  bne   load_fm_points

и тут некоторая проблема.
цикл одну итерацию (где в R12 записано 1) выполяет за одно время (~560нс), а другую (где в R12 записан 0) выполняет на 50 нс дольше (~610нс), а мне очень важно, чтобы они выполнялись за одинаковое время. Сегодня весь день думал над этим, и так не решил эту проблему. Как вы думаете, в чём может быть причина такого безобразного поведения?

P.S. DMA не использую, ибо очень важна производительность, да и к тому же DMA очень уж упоротый в используемом мною камне (использую К1986ВЕ91Т, Cortex-M3)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 01 май 2015, 13:40 
Старожил

Зарегистрирован: 27 мар 2015, 01:22
Сообщения: 1353
Если бы вы формулировали проблему в виде тестовой ассемблерной ф-ции из 10 строчек, а не в виде каши вырванного из контекста кода, то можно было бы разобраться и помочь. Ну и большая вероятность, что в процессе такого формулирования и проблема бы решилась )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 01 май 2015, 13:57 
Старожил

Зарегистрирован: 31 янв 2011, 19:17
Сообщения: 431
Откуда: Москва
Время выполнения инструкций в кортексах не фиксированное. Даже в официальной документации тайминги многих инструкций указаны через тире, т.е. от n до m тактов на инструкцию.
Но если все, кроме одного, цикла выполняются одинаково то попробуйте , к примеру, nop-ами добить время до одинакового


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 01 май 2015, 15:23 
Старожил

Зарегистрирован: 10 июн 2011, 23:01
Сообщения: 3193
Alisa писал(а):
и тут некоторая проблема.
цикл одну итерацию (где в R12 записано 1) выполяет за одно время (~560нс), а другую (где в R12 записан 0) выполняет на 50 нс дольше (~610нс), а мне очень важно, чтобы они выполнялись за одинаковое время. Сегодня весь день думал над этим, и так не решил эту проблему. Как вы думаете, в чём может быть причина такого безобразного поведения?

в цикле оставить только eor r12,r12 тоже отличаться будет?
в чем причина не знаю (конвейер?), но можно немного развернуть цикл
:loop
write_data();
PB7=1;
write_data();
PB7=0;
jump loop;
и добить где надо NOPов чтобы выровнять.
Alisa писал(а):
P.S. DMA не использую, ибо очень важна производительность, да и к тому же DMA очень уж упоротый в используемом мною камне (использую К1986ВЕ91Т, Cortex-M3)

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 01 май 2015, 17:08 
Старожил
Аватара пользователя

Зарегистрирован: 30 мар 2015, 23:56
Сообщения: 690
Ну дык там частота ядра наверное 24мгц , по дефолту.

_________________
Потоковая OS


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 02 май 2015, 05:20 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
_pv писал(а):
в цикле оставить только eor r12,r12 тоже отличаться будет?

нет, время тогда стабильно (хотя, чисто eor r12, r12 в цикле не крутил)
сейчас не могу посмотреть, проект на работе
_pv писал(а):
:loop
write_data();
PB7=1;
write_data();
PB7=0;
jump loop;
и добить где надо NOPов чтобы выровнять.

я тоже думал, и делал (только на C), результат на Си меня не удовлетворил (не помню, почему)
_pv писал(а):
каким бы упоротым не был (хотя я даже даташит сходу не нашел чтобы посмотреть :)), с предсказуемостью (если процессор куда-нибудь усыпить чтобы не мешал)
должно быть получше.
судя по 500-600нс, частоты выдачи данных не особо высокие.

ну вот такой вот у меня контроллер, не особо торопится что-нибудь делать (хотя работает на 80МГц)
если кому интересно, вот даташит на него
http://milandr.ru/uploads/Products/product_80/spec_seriya_1986BE9x.pdf
можно там о Cortex-M3 на русском почитать:)

AVI-crak писал(а):
Ну дык там частота ядра наверное 24мгц , по дефолту.

нет, по дефолту 8МГц, но я PLL-кой умножаю частоту внешнего кварца (16МГц) на 5, получаю 80 МГц, это как раз и есть максимальная рекомендованная частота контроллера. Он, по идее, может работать и на бОльших частотах, но производитель тогда не гарантирует его корректную работу.
P.S. хз, зачем так ограничили, например такой же проц, но с ядром Cortex-M0 (К1986ВЕ1Т) работает на 144МГц

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 02 май 2015, 14:01 
Старожил

Зарегистрирован: 10 июн 2011, 23:01
Сообщения: 3193
процессор для пересылки 6 слов сейчас тратит 80Е6*560Е-9 = 45 тактов. или по 7 тактов на слово.
судя по беглому осмотру документации дма для этого потребуется те же 7 тактов если одиночными и похоже что только 4 такта на слово если данных много подряд.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 03 май 2015, 05:27 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
_pv писал(а):
процессор для пересылки 6 слов сейчас тратит 80Е6*560Е-9 = 45 тактов. или по 7 тактов на слово.
судя по беглому осмотру документации дма для этого потребуется те же 7 тактов если одиночными и похоже что только 4 такта на слово если данных много подряд.

просто сроки поджимают, а осталась только эта проблема (с разным временем выполнения итераций цикла), а с DMA в данном контроллере не разбирался, но судя по отзывам людей, кто с ним пытался работать, DMA в нём не особо тривиален.
Да и к тому же, я не знаю, что будет быстрее: вызвать ассемблерную функцию в прерывании, или в прерывании запускать DMA (получится, как понимаю так: в прерывании запускается DMA, который каждые через 6 слов будет генерировать прерывание, в котором будет дёргать портом. Хз, насколько это будет быстрее)

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

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 04 май 2015, 02:04 
Старожил

Зарегистрирован: 30 апр 2010, 22:56
Сообщения: 1578
Откуда: Киев
DSB вставить, скорее всего процессор что-то оптимизирует при чтении/записи в память


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 05 май 2015, 17:54 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Сегодня, попробовал по одной убирать команды, чтобы выявить кривой момент, и слабое звено было найдено. Нестабильность по времени вносит уменьшение счётчика
Код:
;; уменьшаю счётчик
  subs  r1,  r1,   #1             @@ points_count-- (r1 = points_count, result in r1)

как можно решить эту проблему?
и как правильно (и возможно ли) применить команду dsb к данной проблеме?
Применение ввида
Код:
;; уменьшаю счётчик
  dsb
  subs  r1,  r1,   #1             @@ points_count-- (r1 = points_count, result in r1)

должного эффекта не дало

Если счётчик не уменьшаю (т.е. получаю бесконечный цикл), то всё работает ровно

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 06 май 2015, 11:41 
Старожил

Зарегистрирован: 30 апр 2010, 22:56
Сообщения: 1578
Откуда: Киев
1. Всегда было любопытно, но руки не доходили - попробуйте всунуть инструкции eor.. сразу после использования соответствующего регистра. Там идет подряд две записи в одно устройство внешней памяти, стопудов один такт можно сэкономить. Типа такого:

Код:
  ldrh  r7,  [r5],  #2 ;; пост-инкремент адреса
  strh  r8,  [r3] ;;
  eor   r8,  r8,    #20 ;; меняю адрес
  strh  r7,  [r4]


из той же оперы - поменяйте местами вывод и работу с регистром.
Код:
  str   r12, [r11]                @@ write to register R11 (R11 - bit-band region PB7)
  eor   r12, r12,  #1             @@ xor


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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Ассемблер в Cortex-M3
СообщениеДобавлено: 15 июн 2015, 12:08 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 05 сен 2014, 11:48
Сообщения: 98
Откуда: Saratov
Steel.ne писал(а):
1. Всегда было любопытно, но руки не доходили - попробуйте всунуть инструкции eor.. сразу после использования соответствующего регистра. Там идет подряд две записи в одно устройство внешней памяти, стопудов один такт можно сэкономить.

надеюсь, скоро, руки дойдут:) сделаю такой эксперимент :)
Кстати, проблему решил. Оказалось всё дело в кривой флешке МК. Точнее не совсем уж кривой, но так скажем.. своеобразной:)
Сейчас попробую объяснить (ибо "объясняльщик" из меня никудышный :)
Флеши в контроллере 128Кб, которая разделена на 4 банка (на картинке это Sector A - Sector D)
Примерно вот так ("рисовальщик" тоже из меня никудышный, не пинайте меня :) )
Вложение:
img1.jpg
img1.jpg [ 215.92 Кб | Просмотров: 5861 ]

И данные располагаются в памяти так скажем "кусочками" по 32 бита. Т.е. если записываю 128 бит информации на флешку, если первые 32 бита окажутся в секторе А, то следующие 32 бита окажутся в секторе B, следующие 32 бита в секторе С и т.д.
т.е. примерно так
Вложение:
img2.jpg
img2.jpg [ 216.66 Кб | Просмотров: 5861 ]

и вся беда была в том, что к разным секторам обращение происходит за разное время. Если быть точнее, то к сектору В и D обращение происходит на 50 нс медленнее, нежели чем в сектор А и С. Вот из-за этого безобразия и происходили странные вещи, происхождение которых я так долго не помог понять:)

_________________
Я волшебник.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ] 

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


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

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


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

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

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