Отговори на тема  [ 17 мнения ]  Отиди на страница 1, 2  Следваща
ARM7EJ-S прекъсвания 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4715
Мнение ARM7EJ-S прекъсвания
Имам един джигитайски SoC със ARM7EJ-S ( с малко документация ) и направих една "щуротия" - портнах му FreeRTOS :finga:
обаче порт няма... и сглобих от налични "парчета" (без много мислене) като SAM91 ... и взе, че тръгна :)
тъпото е че всичкото IRQ са на един вектор, а още по тъпото е че 3 таймера са на една маска (имам някъв OS_TIMER с еденична маска, но не съм го разучил)
и ако използвам GPT1 за порт-тикс става мазало...

условно:
Код:
IRQ_Handler() от вектора
    SAVE_CONTEXT
    IRQ_Parse()
        IF GPT
            IF GPT1: GPT1_Handler() SET FLAG !!! тук не мога да сменя контекста !!!
            IF GPT2: GPT2_Handler() за узер
            IF GPT3: GPT3_Handler() за узер
            UNMASK GPT
        IF OTHER
            BLAH-BLAH
    IF FLAG
        CLEAR FLAG
        INCREMENT_TICK
        SWITCH_CONTEXT
    RESTORE_CONTEXT
       


та сложих в GPT1_Handler() един флаг = 1
и като се върна в IRQ_Handler() проверявам за този флаг и джъткам вече тика и контекста
туй бла-бла работи обаче имам YIELD и генерирам SWI 0

Код:
SWI_Handler()
   SAVE_CONTEXT    /* DISABLE ISR ?!?!!? */
   SWITCH_CONTEXT
   RESTORE_CONTEXT /* ENABLE ISR ?!?!!? */


Питанката ми е когато се случи SWI какво става с IRQ
ARM документацията казва, че IRQ автоматично се disable и авто enable при return
демек трябва ли да съм спокоен за SAVE_CONTEXT RESTORE_CONTEXT във SWI

_________________
main[-1u]={1};


Съб Юни 13, 2020 8:51 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4715
Мнение Re: ARM7EJ-S прекъсвания
изобщо не очаквах, че от толкова армаджии няма отговор...

_________________
main[-1u]={1};


Пон Юни 15, 2020 6:43 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: ARM7EJ-S прекъсвания
TheWizard написа:
Питанката ми е когато се случи SWI какво става с IRQ
ARM документацията казва, че IRQ автоматично се disable и авто enable при return
демек трябва ли да съм спокоен за SAVE_CONTEXT RESTORE_CONTEXT във SWI


Както сам си си отговорил при влизане в сервизен режим и изобщо всякакъв режим над юзер прекъсванията се забраняват автоматично. Вече не помня дали 7-цата позволяваше да разрешиш прекъвсванията в сервизен режим, но то не виждам по каква логика ще го правиш. Обикновено системите се проектират така, че сервизния режим да е над прекъсванията, които са OS-aware. Точно с идеята там да напъхаш тред и интеръпт сейф процедури по лесен начин.

Що се отнася до прекъсванията... хич не лоша идея да е само 1 вектор. Проблемът при 7-цата е в това, че интеръпт контролера е по избор на производителя. Но всеки уважаващ себе си производител слагаше NVIC, демек такъв дето поддържа вложени прекъсвания. И тогава съвсем естествено си идва на мястото в общия вектор само да провериш дали си в първо прекъсвание и ако си, да си сейвнеш контекста, да разрешиш прекъсванията и да си извикаш текущото. На излизане само гледаш дали си последен и ако да - затваряш вратата.
Тъпа е по-скоро "модерната" логика да имаш 100-200 вектора и във всеки вектор да проверяваш. Но както и да е, това беше офтопик...


Пон Юни 15, 2020 8:30 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Фев 07, 2012 10:22 pm
Мнения: 3074
Мнение Re: ARM7EJ-S прекъсвания
Цитат:
Tъпа е по-скоро "модерната" логика да имаш 100-200 вектора и във всеки вектор да проверяваш. Но както и да е, това беше офтопик...

Модерна....колко ...40-50г :D
И това беше офтопик :)


Пон Юни 15, 2020 8:53 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4715
Мнение Re: ARM7EJ-S прекъсвания
Миро 10х

NVIC е ама няма да правя сложнотии... системната документация ми липсва - памет, дма, плл... и реверсвам

_________________
main[-1u]={1};


Пон Юни 15, 2020 9:36 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: ARM7EJ-S прекъсвания
Ама сериозно ли се оплакваш че новите имат повече от един вектор???


Вто Юни 16, 2020 8:11 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: ARM7EJ-S прекъсвания
Напълно сериозно!

Ето какъв ми е кода за атмелските АРМ7:

Код:
//------------------------------------------------------------------------------
// IRQ EXCEPTION
//  On entry if REG_CTASK!=0 then the interrupt is not nested and the current
//     task context is saved. On exit, the highest priority task is run.
//  If the interrupt is nested, no context switch is needed
//------------------------------------------------------------------------------

.func IRQ_handler
IRQ_handler:
      sub      lr, lr, #4
      cmp      REG_CTASK, #0
      beq      nested_irq_handler

      str      lr, [REG_CTASK, #tsk_pc]!
      mrs      r11, SPSR
      stmdb    REG_CTASK, {r0-r7, r11-r14}^
      nop
      mov      REG_CTASK, #0
      swp      r0, r0, [REG_AIC_IVR]
      msr      CPSR_c, #ARM_MODE_SVC
      ldmib    r0, {r1, r2}
      mov      lr, pc
      bx       r2            //ISR(r0-info, r1-base)

      msr      CPSR_c, #ARM_MODE_IRQ | I_BIT
      str      r0, [REG_AIC_IVR, #AIC_EOICR - AIC_IVR]
return_to_current_task:
      ldr      REG_CTASK, [REG_MTASK, #tsk_renext]
      add      r11, REG_CTASK, #tsk_pc
      ldr      lr, [r11]
      ldmdb    r11, {r0-r7, r11-r14}^
      nop
      msr      SPSR_cxsf, R11
      movs     pc, lr

nested_irq_handler:
      stmfd    sp!, {r0-r5, r12, lr}
      mrs      r4, SPSR
      swp      r0, r0, [REG_AIC_IVR]
      msr      CPSR_c, #ARM_MODE_SVC
      mov      r5, lr
      ldmib    r0, {r1, r2}
      mov      lr, pc
      bx       r2            //ISR(r0-info, r1-base)

      mov      lr, r5
      msr      CPSR_c, #ARM_MODE_IRQ | I_BIT
      str      lr, [REG_AIC_IVR, #AIC_EOICR - AIC_IVR]
      msr      SPSR_cxsf, R4
      ldmfd    sp!, {r0-r5, r12, pc}^
.endfunc
.func SWI_handler


Това включва влизане в прекъсване, обработка на вложените прекъсвания, спасяване на контекста, възстановяване на контекста. Включва още поддръжка на драйвери, щото NVIQ-a не се програмира с указатели към функции, а указатели към драйвери...
И всичко е само този код. При куртексите е пръснат на 100 места, налагат се 100 трика, изобщо боза!


Вто Юни 16, 2020 8:27 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: ARM7EJ-S прекъсвания
И как стои въпросът със закъснението на обработката на прекъсванията, особено ако имаш софтуерно приоритизиране? На дъртите и ние слагахме подобни дивотии, ама това яде време да се изпълни.
В какъв смисъл кодът е разхвърлян? На разните вектори са различните хендлъри, които нямат нищо общо помежду си. Общ код няма - освен ако не стигат векторите/приоритетите и искаш да ги разшириш още повече софтуерно - т.е. когато искаш да имаш много софтуерни тредове. Ама то при кортексите има достатъчно място за още няколко софтуерни прекъсвания, когато хардуерните не стигат, или, по-точно, като имаш нужда от едно хардуерно събитие да се "разклониш" и избереш една от няколко линии на обработка с друг приоритет.
Ако тръгнеш в посоката да си правиш тредове заради самите тях, т.е. заради ОС-а или модела на обработка, ще ти трябват много "изкуствени" тредове, което си е проблем на дизайна. И пак не виждам защо да не ползваш наличните множество вектори/приоритети от хардуера, и да си добавиш колкото ти трябва за "софтуерните" - т.е. хардуерните обслужват I/O-процесите, а оттам насетне приложението добавя шедюлър (ако има нужда). Все пак доста работа се свършва от хардуера и няма смисъл да не се ползват наличните функционалности, поне за най-бързите процеси/събития.

Дъвкали сме го много, но все пак - защо да не си сложа подходящия код в "UART TX ready" прекъсването и там директно да да видя има ли още в буферите за предаване към TX фифо-то на УАРТ-а, оставяйки който както иска от другата страна помпи във софтуерния буфер? Какво повече ми трябва, за да направя буферирано I/O? Защо да съм задължен да хвана прекъсването и да събудя софтуерен тред на шедюлъра, който да извади от буфера и да прави нещо нанатък - може би да събуди друг тред, който да измисли какво да праща... Сещам се за една причина - ако хардуера е дървен и не ми предоставя прекъсване "tx ready", или ако мина на polling понеже overhead-а от обработките на прекъсвания са ми казали да не ползвам прекъсване.
Мисля си че целта е максимално бързо да се разбере че има място във фифото и трябва да го допълним с още данни - колкото по-бързо и сигурно стигнем до това заключение и почнем обработката на точния код за допълване. Ако има някаква дупка в хардуерното преценяване има логика да трупаме код - ама ако няма не е ли безсмислено?

Едит: какво е указател към драйвер и в кой стандарт е дефинирано? Това че C++ обектите не могат да се викат през указател към функция си е "специфика" на езика и има решение, което всъщност е C решението за обект. Не виждам защо кусур на определен език ще определя дизайн на хардуера - особено за език, който се бие да е най-доброто за "системно програмиране" :rolleyes:


Вто Юни 16, 2020 3:47 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: ARM7EJ-S прекъсвания
Мда... дъвкали сме го много пъти, ама напредък йок ;-)

Ти се опитваш през твоята камбанария да гледаш света, обаче в случая аз ползвам една по-утъпкана пътека с банален ОС и банално/стандартно изпълнение.
Баналното изпълнение включва нишки, които си щъкат отдолу. Могат да се сменят доброволно или доброзорно. Вика му се шедулинг алгоритъм.
При доброволното нишката казва "аз ша спя" при което вика сервизната функция за спане и тя трябва да спаси контекста на нишката, да вземе друг контекст на друга нишка, да го възстанови и при излизане хуква новия контекст демек нишка.
При доброзорната смяна идва външен сигнал, т.е. прекъсване. Не всяко прекъсване сменя нишки естествено. Просто нишки дето чакат хардуера на практика чакат някакво прекъсване. За да е още по-реално, прекъсванията могат да идват накуп, т.е. докато обработваш едно посредата идва друго и така нишките за събуждане може да са няколко, ама ти трябва да събудиш само едно естествено.
Цялата тая дандания има различни имплементации. При по-простите може да се действа с конкретика. Демек в прекъсването решаваш дали ще сменяш контексти и т.н. Фреертос-а май беше на тоя принцип. Проблемът е, че става мазало щото не спасиш ли контекста преди първото прекъсване и позволиш второ и то реши да сменя вече не е ясно какво ще сменя и т.н. Затова има по-чисто решение. При първо прекъсване текущия контекст се спасява. При последно се възстановява. По средата под "текущ контекст" се разбира указателя към текущата нишка. Няма проблем този указател да се променя N пъти, т.е. може да имаш 100 вложени прекъсвания, всяко може да си сигнализира нишки и да събужда и да убива, въобще може да става всичко без проблем.
На въпроса за драйвер - драйвера е всичко, което ти е необходимо за да обслужваш дадена периферия. Джелязна или виртуална, все тая. Работата е там, че някои периферии се дублират и често по повече от един път. Примерно може да имаш 5 UART-a. И тъй като под "драйвер" се разбира нещо стандартно, то няма никаква логика за 5 еднакви хардуера да имаш 5 различни софтуера. Говорим за един драйвер за UART, който може да се инсталира 5 пъти или колкото там искаш. И под инсталация е добре да не са 5 набора от макроси дето генерират 5 комплекта процедури, щото не е много ефикасно така по 5 пъти. И те така стигаме до един набор от функции, които НЕ СЕ дублират. Както и при обектното програмиране. Имаш клас, имаш и инстанция. Но реално обекта ти представлява един указател. От този указател може да извлечеш всичко за инстанцията и/или класа. Абсолютно по същия начин е при драйверите - имаш указател (или индекс) от който може да стигнеш до каквото ти трябва...
Сега какво става, когато имаш общ вектор на прекъсванията. Както казах NVIQ-а се програмира не с указатели към ISR, а с указатели към драйвери. Идва прекъсване, влизаш в общия вектор, четеш един указател от тип драйвер, викаш функцията за прекъсване на тоя драйвер. Естествено тъй като тази функция е "виртуална" трябва да й подадеш параметър (this) на конкретния драйвер. Тоя параметър си е същия указател с който си програмирал контролера на прекъсванията.
Какво става ако няма общ вектор - ми ти нямаш 5 отделни процедури за UART примерно. Така че и да имаш 5 отделни вектора това не ти помага, ти пак трябва да отидеш на едно място. Само дето се налага първо да отидеш на някое от 5-те места, да видиш на кое си отишъл, да си сметнеш кой ти е тоя драйвер и след това да извикаш функцията му за прекъсване. Така цялото ускорение от хардуерното диспатчване отива на кино, щото софтуерно се налага да го ревърснеш...
За да е още по-шантово излизането при куртексите и допълнително усложнено. Реално в прекъсване не знаеш при излизане дали ще излезеш или ще влезеш в друго, щото има там една заигравка и пестят от спасяване на регистри. Демек при излизане от прекъсване не можеш да възстановяваш контексти. Прави се чрез pending прекъсване, което трябва да сложиш с по-нисък приоритет от най-ниското нормално прекъсване и трябва да се аборнираш за него, то евентуално да възстанови контекста. Освен ако него не го прекъснат, тогава ще възстанови един, ще зацикли и възстанови друг.
И за да е още по-шантово, покрай всичките тия "ускорения" при викане на софтуерно прекъсване не може да ползваш регистри. Не знаеш дали някой няма да те прекъсне и да ги омаже. Софтуерните прекъсвания трябва да претакват параметрите си през стека. На излизане пък резултатът се претаква...
И за да е още по-шантово всичките тия прекъсвания на прекъсвания и оптимизации стават много капризни на тема приоритети и инверсия на приоритети. Имаш и хардуерни стекове за тия приоритети. Съответно имаш хард фаулт, ако се омажат и трябва да гледаш да не ги омазваш, въобще манджа с грозде...

С две думи, четвърта архитектура е архитектурата, която е подходяща за ОС. При куртексите я омазаха... и после пак се върнаха на нея.


Вто Юни 16, 2020 5:03 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 8:22 am
Мнения: 15501
Местоположение: София
Мнение Re: ARM7EJ-S прекъсвания
miro_atc написа:
Сега какво става, когато имаш общ вектор на прекъсванията. Както казах NVIQ-а се програмира не с указатели към ISR, а с указатели към драйвери. Идва прекъсване, влизаш в общия вектор, четеш един указател от тип драйвер, викаш функцията за прекъсване на тоя драйвер. Естествено тъй като тази функция е "виртуална" трябва да й подадеш параметър (this) на конкретния драйвер. Тоя параметър си е същия указател с който си програмирал контролера на прекъсванията.
Какво става ако няма общ вектор - ми ти нямаш 5 отделни процедури за UART примерно. Така че и да имаш 5 отделни вектора това не ти помага, ти пак трябва да отидеш на едно място. Само дето се налага първо да отидеш на някое от 5-те места, да видиш на кое си отишъл, да си сметнеш кой ти е тоя драйвер и след това да извикаш функцията му за прекъсване. Така цялото ускорение от хардуерното диспатчване отива на кино, щото софтуерно се налага да го ревърснеш...


Т.е. при примера с UART-а na Cortex-a прекъсването ще се развърже НЕ по-бавно от на стария ARM. Т.е. не губиш нищо, реално е същото, а според мен и една идея по-бързо. Просто трябва да извикаш УАРТ драйвера с някакво ID или хендъл и толкоз. А понеже си в точно определено прекъсване, то и този хендъл е недвусмислено ясен в момента на прекъсването. Тук не коментираме извратеностите на STM да комбинират по няколко сорса на един вектор, особенно ако говорим за пинови прекъсвания.

Обаче ако трябва да отработиш някакво специфично прекъсване, което не изисква унификация със себеподобни, отделните вектори са много по-удобни, защото уникалния код си живее в собствен контекст още от евента и не си меша капите с другите.

Т.е. по отношение на прекъсванията Кортекса е по - добре или в най-лошия случай равен на ARM7, не е ли тъй?

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Вто Юни 16, 2020 6:15 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: ARM7EJ-S прекъсвания
Тъй де. И когато има нужда от "унификация на себеподобни" най-простият начин е да сложиш отделни прости хендлъри на всеки отделен вектор, като uart0_int(), uart1_int() и т.н. Всяка от тях просто вика още една - унифицираната, примерно uart_common_int(&UART0context) за уарт0, и т.н. А пък който иска може да слага едно и също на всички вектори, и после още веднъж да търси информация как да стигне до уникалните - но това е цената на наследството - направено за общ вектор понякога преминава нататък, в следващата генерация, нищо че вече има отделни, и остава софтуерния диспатч (при положение че целия интеръпт контролер е мислен за да спести този софтуерен слой).
Мисля, че е по-лесно да обединиш (омешаш) разни съставки в едно, отколкото да разделиш от кюпа отделните.


Вто Юни 16, 2020 7:33 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4715
Мнение Re: ARM7EJ-S прекъсвания
да де ама ако имаш N таймера на един вектор, сис-тика и смяна на контекста става мазало
намерих OS_TIMER...(от недокументираните) ще тествам да го пусна на 1 мс IRQ, че е сам на вектор

Тоя SoC е MT6261 / МТ250х - на джигитайските 2G модули чипсета ( 260MHz с по 4 мега флаш и рам )
затрих му firmware и цъка FreeRTOS и Ардуино - бареметал ( no GSM )
подкарах му и блутута, ама немам "лесен" стек за BT 3.0 ... със BLE стек вика, че не разбира командите

_________________
main[-1u]={1};


Вто Юни 16, 2020 8:03 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Сеп 26, 2004 8:21 pm
Мнения: 27998
Местоположение: София
Мнение Re: ARM7EJ-S прекъсвания
Ами когато имаш някакъв ОС/по адванс шедулър не мога да кажа до колко има смисъл от много вектори, няма достатъчно о-ит, но ако караш без такъв, а според мен малките армове нямат нужда от подобни екстри, конкретно ОС-и, то многото вектори започвт да са критични когато искаш да изтискаш максимума от един контролер. Да прави се и с едно прекъсване, като на дъртите пикльовци, не е да не съм ги изстисквал до максимум, но многото вектори в много случаи си имат предимства. Примерно реализацията при 51-ците на силабс е много по-удобна от един вектор при дъртите 16-ки.


Вто Юни 16, 2020 10:31 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10368
Местоположение: Добрич
Мнение Re: ARM7EJ-S прекъсвания
Цецо написа:
Т.е. не губиш нищо, реално е същото, а според мен и една идея по-бързо.


Като скорост - да. Операциите по завързване и развързване са еднакви, но инструкшън сета на куртекса е по-добър и става с две, докато на стария трябват поне 3 инструкции. Допълнителното ускорение на куртекса идва от спасяването на регистрите, което го прави в прелюдията. Но макар, че това спестява няколко клока също създава главоболия, защото понякога се прави, понякога не се прави. Съответно не може да разчиташ на регистри в софтуерните прекъсвания.
С две думи при куртекса има много "ускорения", които заради няколко клока усложняват и бъркат доста неща. Не случайно се ползват само в куртекс-М, при всички останали си е класическата концепция.
А пък ST са уникати... не им стига отделен вектор за периферия, ами някои периферии като USB могат да имат по два вектора. Разбирам да беше за критични периферии като да кажем таймери, които може да искаш да ги пуснеш да цвъкат през микросекунди. А те слагат по няколко таймера на общ вектор, пък USB се шири на два.

TheWizard написа:
да де ама ако имаш N таймера на един вектор, сис-тика и смяна на контекста става мазало
намерих OS_TIMER...(от недокументираните) ще тествам да го пусна на 1 мс IRQ, че е сам на вектор


По принцип ако спасяваш и възстановяваш винаги контекста при влизане/излизане от първо ниво прекъсване ОС-а се опростява значително. Нямаш нужда сис-тика да ти е специален, нямаш нужда от нищо. Допълнително опростяване е ако важните системни функции са ти софтуерни прекъсвания. Така ти отпада и нуждата да забраняваш прекъсвания и всякакви гимнастики по синхронизации.
Не помня точно как беше при фреертоса... той май слагаше save/restore във всеки ISR, който иска да ползва кърнела? Аз се възползвах от атмелите, при които може да избираш всеки вектор дали да ти прави IRQ или FIQ. Съответно контекстите ги спасявах за всички IRQ-та още в хендлъра. А ако за нещо няма нужда да се спасяват контексти просто го пусках като FIQ и там хендлъра е чист и бърз.


Сря Юни 17, 2020 8:45 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Апр 27, 2005 11:48 am
Мнения: 4715
Мнение Re: ARM7EJ-S прекъсвания
....той май слагаше save/restore във всеки ISR.... - аха

подкарах OS_TIMER - той бил "умен" ( има отделен вътрешен ARM за системни операции, систик, слип, вейкъп...) ... един таймер IRQ и един брояч сис-тик-брояч :)
тея са му набутали няколко ARM-a и няколко DSP периферии ... баси

_________________
main[-1u]={1};


Сря Юни 17, 2020 1:19 pm
Профил ICQ
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 17 мнения ]  Отиди на страница 1, 2  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 4 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни