Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: AT91SAM7S новичок
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Xeon
Всем доброго времени суток!!! Имеется платка с AT91SAM7S. Подскажите пожалуйста как использовать прерывания или где посмотреть, примеры.
Очень буду признателен!
Lotor
Вероятнее всего с Вашей платкой примеры и идут.

PS: А вообще гугл или документация к Вашему компилятору в помощь.
PPS: Общие положения: в асм файле на место вектора исключения помещается команда безусловного перехода по адресу AIC_IVR, а обработчики в сишных файлах объявляются с атрибутами __arm __irq (для iar).
Xeon
Цитата(Lotor @ Dec 19 2011, 10:45) *
Вероятнее всего с Вашей платкой примеры и идут.


Платку сам делал) поэтому примеров нет)
Lotor
Цитата(Xeon @ Dec 19 2011, 10:46) *
Платку сам делал) поэтому примеров нет)

Но задан на столько общий вопрос, что подойдут примеры от любых других платок с Вашим контроллером.
Xeon
Цитата(Lotor @ Dec 19 2011, 10:56) *
Но задан на столько общий вопрос, что подойдут примеры от любых других платок с Вашим контроллером.


Буду очень благодарен если дадите ссылочки)

ЗЫ. Использую Keil.

Цитата(Lotor @ Dec 19 2011, 10:45) *
Вероятнее всего с Вашей платкой примеры и идут.

PS: А вообще гугл или документация к Вашему компилятору в помощь.
PPS: Общие положения: в асм файле на место вектора исключения помещается команда безусловного перехода по адресу AIC_IVR, а обработчики в сишных файлах объявляются с атрибутами __arm __irq (для iar).


А каким образом узнать от какой перефирии было прерывание?
Lotor
Цитата(Xeon @ Dec 19 2011, 11:00) *
Буду очень благодарен если дадите ссылочки)

Не серьезно же просить гуглить за себя... sm.gif
Например - http://www.atmel.com/dyn/products/tools_ca...sp?tool_id=3784
Цитата(Xeon @ Dec 19 2011, 11:00) *
А каким образом узнать от какой перефирии было прерывание?

Почитайте в документации на свой контроллер про AIC.
Идея в следующем:
Адреса обработчиков прерываний могут быть сохранены в регистрах AIC_SVR1...AIC_SVR131. В регистре AIC_IVR хранится значение регистра AIC_SVRn, который соответствует текущему прерыванию. Поэтому Вам следует разместить по адресу прерывания ARM переход на AIC_IVR.
Xeon
Lotor Спасибо!!! rolleyes.gif
kovigor
Цитата(Xeon @ Dec 19 2011, 09:35) *
Всем доброго времени суток!!! Имеется платка с AT91SAM7S. Подскажите пожалуйста как использовать прерывания или где посмотреть, примеры.
Очень буду признателен!


Кейл сам дает целую кучу примеров чуть не для любого МК:

http://www.atmel.com/dyn/products/tools_ca...sp?tool_id=4343
Xeon
Получается что в AT91SAM7S может использоваться 32 источника прерываний одновременно?

Если надо использовать несколько прерываний от одной периферии (например усарта), то когда перейдём по вектору надо смотреть флаги которое из них сработало?
Xeon
Люди а как правильно делать выход из прерывания? А то зайти то зашёл, а при выходе зависает (смотрел отладчиком кейла, зависает а конце обработчика прерывания). Если нужно приведу код...
toweroff
посмотрите документацию на контроллер прерываний вашего проца
но уж как минимум сбросить флаг прерывания
Xeon
Цитата(toweroff @ Dec 20 2011, 09:00) *
посмотрите документацию на контроллер прерываний вашего проца
но уж как минимум сбросить флаг прерывания


Т.е. автоматом это не происходит?

Получается что в AT91SAM7S может использоваться 32 источника прерываний одновременно?

Если надо использовать несколько прерываний от одной периферии (например усарта), то когда перейдём по вектору надо смотреть флаги которое из них сработало?
toweroff
Цитата(Xeon @ Dec 20 2011, 10:02) *
Т.е. автоматом это не происходит?

читать надо мануал. Вроде как нет, но с атмелем не работал

Цитата(Xeon @ Dec 20 2011, 10:02) *
Получается что в AT91SAM7S может использоваться 32 источника прерываний одновременно?

мало того, так еще и с назначаемыми приоритетами

Цитата(Xeon @ Dec 20 2011, 10:02) *
Если надо использовать несколько прерываний от одной периферии (например усарта), то когда перейдём по вектору надо смотреть флаги которое из них сработало?

конечно
Xeon
Спасибо toweroff!
А как правильно в keil делать разделения на .c и .h? Делаю как обычно в .h прототипы в .c описываю сами функции, подключаю в main .h и в итоге ошибка: L6218E Undefine simbol "название функции"...
toweroff
выкладывайте... так сложно сказать
Lotor
Цитата(Xeon @ Dec 20 2011, 10:28) *
Спасибо toweroff!
А как правильно в keil делать разделения на .c и .h? Делаю как обычно в .h прототипы в .c описываю сами функции, подключаю в main .h и в итоге ошибка: L6218E Undefine simbol "название функции"...

Скорее всего Вы просто не прицепили хидер к проекту.

PS: Я сейчас кощунственную вещь скажу для этого форума, но есть книга Редькина с переводом документации на Ваш мк. Почитайте.
Xeon
Цитата(Xeon @ Dec 20 2011, 09:28) *
Спасибо toweroff!
А как правильно в keil делать разделения на .c и .h? Делаю как обычно в .h прототипы в .c описываю сами функции, подключаю в main .h и в итоге ошибка: L6218E Undefine simbol "название функции"...


Ну с этим разобрался, сам затупил немного (где main вписал extern "C" {"подключаемые хедеры"}, а в хедерах перед прототипом extern)

Цитата(Lotor @ Dec 20 2011, 09:50) *
Скорее всего Вы просто не прицепили хидер к проекту.

PS: Я сейчас кощунственную вещь скажу для этого форума, но есть книга Редькина с переводом документации на Ваш мк. Почитайте.


Если это 32-16 битные микроконтроллеры ARM7 фирмы Atmel то полистал...книга-бякя...лучше даташит читать...с инглишом ещё немного дружу)
Lotor
Цитата(Xeon @ Dec 20 2011, 11:06) *
Если это 32-16 битные микроконтроллеры ARM7 фирмы Atmel то полистал...книга-бякя...лучше даташит читать...с инглишом ещё немного дружу)

Тем не менее в этой бяке есть все ответы на ранее заданные Вами вопросы. =)
Xeon
Цитата(Lotor @ Dec 20 2011, 10:25) *
Тем не менее в этой бяке есть все ответы на ранее заданные Вами вопросы. =)


Значит надо найти силы её ещё разок почитать sm.gif

Вроде чего-то добился) только вот незадача прерывание срабатывает только один раз...)
Привожу код (В Led.h две функции инициализировать ноги и помыргать светодиодами):
Код
#include <at91sam7s128.h>

extern "C" {
#include "Led.h"
}

unsigned char send_val = 0xA0;

void Usart_TX(void) //__irq
{
     unsigned int status;
        // Read USART status
        status = AT91C_BASE_US0->US_CSR;

    if(status & AT91C_US_TXEMPTY)
    {
        AT91C_BASE_US0->US_THR = (unsigned short) send_val;
        send_val++;
    }
}

int main(void)
{
    // Configure PIO
    AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA6;
        AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA6;
    AT91C_BASE_PIOA->PIO_OER |= AT91C_PIO_PA6;

    // Enable usart
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
    // Reset and disable receiver & transmitter
        AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
        // Configure mode
    AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE;
        // Configure baudrate
        // Asynchronous, no oversampling
        AT91C_BASE_US0->US_BRGR = 104;

    // Enable interrupt
    AT91C_BASE_US0->US_IER                         = AT91C_US_TXEMPTY;
    AT91C_BASE_AIC->AIC_IDCR                     = 1 << AT91C_ID_US0;
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0]        = 0;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0]         = (unsigned int) &Usart_TX;
    AT91C_BASE_AIC->AIC_IECR                     = 1 << AT91C_ID_US0;
    // Clear interrupt
        AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_US0;

    // enable rx and tx
    AT91C_BASE_US0->US_CR = AT91C_US_TXEN | AT91C_US_RXEN;


    // Leds
    Led_Init();    


    while(1)
    {
        Blink();
    }
}
toweroff
а зачем __irq закоментили?
и где сброс флага прерывания?
Xeon
Закоментил потому что в примерах нету __irq а вроде прерывание используется...
Сейчас ток запустил... к тому коду добавил следующее:
в конец обработчика прерывания строку
AT91C_BASE_AIC->AIC_EOICR = 0;
и раскоментил __irq
в сумме получил следующий код:

Код
#include <at91sam7s128.h>

extern "C" {
#include "Led.h"
}

unsigned char send_val = 0xA0;

void Usart_TX(void) __irq //!!!!!!!!!!!!!!!!!!! тут раскоментил !!!!!!!!!!!!!!!!!!!!!!!!!!!
{
     unsigned int status;
        // Read USART status
        status = AT91C_BASE_US0->US_CSR;

    if(status & AT91C_US_TXEMPTY)
    {
        AT91C_BASE_US0->US_THR = (unsigned short) send_val;
        send_val++;
    }
    AT91C_BASE_AIC->AIC_EOICR = 0; // !!!!!!!!! тут добавил !!!!!!!!!!!!!!!!!!!!!!!!!!
}

int main(void)
{
    // Configure PIO
    AT91C_BASE_PIOA->PIO_ASR = AT91C_PIO_PA6;
        AT91C_BASE_PIOA->PIO_PDR = AT91C_PIO_PA6;
    AT91C_BASE_PIOA->PIO_OER |= AT91C_PIO_PA6;

    // Enable usart
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_US0;
    // Reset and disable receiver & transmitter
        AT91C_BASE_US0->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS;
        // Configure mode
    AT91C_BASE_US0->US_MR = AT91C_US_USMODE_NORMAL | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE;
        // Configure baudrate
        // Asynchronous, no oversampling
        AT91C_BASE_US0->US_BRGR = 104;

    // Enable interrupt
    AT91C_BASE_US0->US_IER                         = AT91C_US_TXEMPTY;
    AT91C_BASE_AIC->AIC_IDCR                     = 1 << AT91C_ID_US0;
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_US0]        = 0;
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_US0]         = (unsigned int) &Usart_TX;
    AT91C_BASE_AIC->AIC_IECR                     = 1 << AT91C_ID_US0;
    // Clear interrupt
        AT91C_BASE_AIC->AIC_ICCR = 1 << AT91C_ID_US0;

    // enable rx and tx
    AT91C_BASE_US0->US_CR = AT91C_US_TXEN | AT91C_US_RXEN;


    // Leds
    Led_Init();    


    while(1)
    {
        Blink();
    }
}


И УРА заработало!))))

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

Мой код: Нажмите для просмотра прикрепленного файла

Пример: Нажмите для просмотра прикрепленного файла

В примере открывал проект: basic-usart-hw-handshaking-project-at91sam7s-ek\at91sam7s-ek\basic-usart-hw-handshaking-project\uv2\at91sam7s128.uvproj
kovigor
Цитата(Xeon @ Dec 20 2011, 11:06) *
книга-бякя...лучше даташит читать...с инглишом ещё немного дружу)


Ложь ! Читаю даташиты почти без словаря, но Редькина прочитываю первым. Хотя бы потому, что это чтение позволяет быстро и качественно получить общую информацию. Ну а детали можно уже и в даташите уточнить ...
Xeon
Цитата(kovigor @ Dec 20 2011, 12:21) *
Ложь ! Читаю даташиты почти без словаря, но Редькина прочитываю первым. Хотя бы потому, что это чтение позволяет быстро и качественно получить общую информацию. Ну а детали можно уже и в даташите уточнить ...


А без деталек чет ничего работать не хочет sm.gif
Xeon
Возникла ещё одна проблема)...
Создас файлики Protocol.c и Protocol.h в хедере описал все нужные переменные как static прототипы функций как extern (иначе не компилится, может так нельзя в кейле?).
В main подключаю хедеры следующим образом:
extern "C" {
#include "Protoloc.h"
#include "Led.h"
}
Led.h - там две функции одна инициализирует порты другая моргает светодиодами (объявлены как extern). Так вот когда вызываю функцию из Led.h все норм. Когда же вызываю функция из Protocol.h то программа зависает на строке SWI_Handler B SWI_Handler (строка из файла SAM7.s где происходит начальная инициализация). Смотрел кейловским отладчиком. В чём причина...?


Забыл сказать...смотрел стандартным дебагом переход на строку SWI_Handler B SWI_Handlerс происходит при переходе на функцию main(), т.е. после команд:
ldr r0, =__main
bx r0

Нашел причину...у меня есть строка ParseBuf = (unsigned char*) malloc(size); если её коментю то все норм, если эта строка есть то происходит выше сказанное...
Может нужно переопределять какие-то определения или есть хитрость при работе с библиотекой stdlib?
Lotor
Вы для кучи память выделили же?
Xeon
Опа...) нет...) а как это сделать?)
Lotor
Цитата(Xeon @ Dec 21 2011, 12:00) *
Опа...) нет...) а как это сделать?)

Если у Вас Кеил, то к проекту должен быть подключен стартаповый файл (расширение .s), если перейдете на него, то внизу будет вкладка Config Wizard.
Xeon
Цитата(Lotor @ Dec 21 2011, 11:11) *
Если у Вас Кеил, то к проекту должен быть подключен стартаповый файл (расширение .s), если перейдете на него, то внизу будет вкладка Config Wizard.

А какой обьём лучше выставлять, есть тут ли какие либо правила... или главное чтоб ОЗУ хватило?
toweroff
Цитата(Xeon @ Dec 21 2011, 12:15) *
А какой обьём лучше выставлять, есть тут ли какие либо правила... или главное чтоб ОЗУ хватило?

а это уж как будете кучу пользовать sm.gif
со стеками несколько проще, кейл может рассчитать глубину (максимальную) вызовов... однако, если используются указатели на функции или еще как-то, может не совсем корректно вычисляться. Самому нужно прикидывать размеры
Xeon
Цитата(toweroff @ Dec 21 2011, 11:18) *
а это уж как будете кучу пользовать sm.gif
со стеками несколько проще, кейл может рассчитать глубину (максимальную) вызовов... однако, если используются указатели на функции или еще как-то, может не совсем корректно вычисляться. Самому нужно прикидывать размеры

Прикинул...выделил... Всё понял!)
toweroff и Lotor БОЛЬШОЕ СПАСИБО!!!!!! rolleyes.gif

И снова вопрос)
Как я понял в ARM если ты под юзером то прерывание глобально отрубить не как... а если очень нужно то как это сделать?
Или можно чтоб программа всё время выполнялась под каким нить другим режимом, который имеет подобные права, например supervisor?
aaarrr
Цитата(Xeon @ Dec 21 2011, 12:46) *
Как я понял в ARM если ты под юзером то прерывание глобально отрубить не как... а если очень нужно то как это сделать?

Нужно попросить супервизор (через SWI, например).

Цитата(Xeon @ Dec 21 2011, 12:46) *
Или можно чтоб программа всё время выполнялась под каким нить другим режимом, который имеет подобные права, например supervisor?

Можно.
Xeon
Цитата(aaarrr @ Dec 21 2011, 12:10) *
Нужно попросить супервизор (через SWI, например).


Можно.


А как вызвать SWI на С? Или просто делать ассемблерную вставку? и как указать обработчик программного прерывания?

Если буду находиться всё время в супервизоре это нормально или плохой тон?
aaarrr
Цитата(Xeon @ Dec 21 2011, 13:32) *
А как вызвать SWI на С? Или просто делать ассемблерную вставку? и как указать обработчик программного прерывания?

В RVCT, например, объявляется прототип вида
__swi(XX) int func(int, int)
а затем в программе просто используете эту функцию.
Но придется писать свой обработчик SWI, и тут уже без асма не обойтись.

Цитата(Xeon @ Dec 21 2011, 13:32) *
Если буду находиться всё время в супервизоре это нормально или плохой тон?

Если не используется ОС, то нормально. Если используется, то она будет жить в SVC, а задачи - в USER/SYSTEM.
Xeon
Возникла следующая ситуация (смотрел стандартным отладчиком):
как уже писал выше есть разделения кода на файлы (есть главный файл main, Protocol.h хранит некоторые переменные, объявленные как static, и прототипы, объявленные как extern и использующие эти переменные...) в главном файле соответственно прописано:
extern "C" {
#include "Protocol.h"
...
}
Так вот, когда пытаюсь обратиться к статическим переменным, объявленным в Protocol.h из главного файла, то в них хранятся нули... а когда из Protocol.c то всё норм.
Это дело возникает скорее всего из-за ограничения видимости этих самых переменных (так как они в файле объявлены глобально и как статические, их видимость заканчивается на этом же файле, в моём случае Protocol.c... или я неправ?)
Конечно, можно решить проблему следующим образом: создать в Protocol функции которые бы возвращали значения этих переменных... но... неужели в кейле нет чего-нить проще? И почему кейл не позволяет объявлять переменные и функции в разных файлах например как visual studio (там не требуется не каких static и extern)???

Ну и тут же в голову влез ещё один вопрос! Так как есть доступ к этим переменным из Protocol и из main, но в первом случае всё заполнено нулям, а во втором нормальными данными, при этом у меня изменяются значения только в Protocol, а в main я их не изменяю... может быть компилятор создал две копии каждой переменной... и одни доступны только для main другие только для Protocol?

Цитата(Xeon @ Dec 22 2011, 10:21) *
Ну и тут же в голову влез ещё один вопрос! Так как есть доступ к этим переменным из Protocol и из main, но в первом случае всё заполнено нулям, а во втором нормальными данными, при этом у меня изменяются значения только в Protocol, а в main я их не изменяю... может быть компилятор создал две копии каждой переменной... и одни доступны только для main другие только для Protocol?


На этот вопрос сам и ответил... именно так и происходит... компилятор создаёт два варианта переменных одни доступны для main другие для Protocol (проверил следующим образом: изменял их и в файле main и в файле Protocol, и там и там находились значения которые записывал...естесно разные но правильные). И если убираю static у переменных то начинает ругаться линковщик: типа множественное определение там-то и там-то...
Так как правильно в кейле делать разделения программы на файлы?
Lotor
А зачем в Вашем случаи делать глобальные переменные статическими? Вы уверены, что до конца понимаете смысл своих действий? Статические глобальные переменные уникальны для каждой единицы трансляции. И это стандарт, а не особенность компилятора.

Цитата(Xeon @ Dec 22 2011, 11:28) *
Так как правильно в кейле делать разделения программы на файлы?

Кеил не требует нестандартных движений для этого.
Xeon
Цитата(Lotor @ Dec 22 2011, 11:35) *
А зачем в Вашем случаи делать глобальные переменные статическими? Вы уверены, что до конца понимаете смысл своих действий? Статические глобальные переменные уникальны для каждой единицы трансляции.


Может понимаю конечно не до конца... но если я убираю слово static перед, объявлением появляется ошибка: L6200E: Symbol blablabla multiply definition (by Protocol.o and main.o)

Я как понимаю это ошибка линковщика, типо я объявляю и там и там... так оно и происходит компилятор всовывает и там и там, проверил вышеописанным способом)
Lotor
Цитата(Xeon @ Dec 22 2011, 12:42) *
Может понимаю конечно не до конца... но если я убираю слово static перед, объявлением появляется ошибка: L6200E: Symbol blablabla multiply definition (by Protocol.o and main.o)

Т.е. Кеил виноват? В Protocol.h пишите
Код
extern int  blablabla;

В Protocol.c делаете глобальную переменную
Код
int  blablabla = 10;

Хидер подключаете к main.c или любому другому файлу, где хотите иметь доступ к blablabla.
Xeon
Только что создал новый проект... в нем 3 файла pp.h, pp.c, и main

код pp.h:
Код
#ifndef PP_H
#define PP_H

int constanta = 2;

int add_2(int a);

#endif


код pp.c:
Код
#include "pp.h"

int add_2(int a)
{
    a = constanta;

    return a;
}


код main.c:
Код
#include <at91sam7s128.h>
#include "pp.h"

int main(void)
{
    int a;
    a = 2;

    a = add_2(a);

    return a;
}


На всякий пожарный sm.gif, сам проект:Нажмите для просмотра прикрепленного файла

И тут тоже такое...

Цитата(Lotor @ Dec 22 2011, 11:47) *
Т.е. Кеил виноват? В Protocol.h пишите
Код
extern int  blablabla;

В Protocol.c делаете глобальную переменную
Код
int  blablabla = 10;

Хидер подключаете к main.c или любому другому файлу, где хотите иметь доступ к blablabla.


Теперь понил...
Ну например visual studio не каких extern не требует...

Тут же есть моментик... открываю проект для stm32чётотам ) и там нет ни каких extern...есть обычное объявление глобальных переменных в разных файлах и никаких руганьев компилятора или линковщика....

Компилятор один.... в чём разница... настройки сравнил все... всё одинаково, за исключением камня...

Ну и там же для stm в проекте где есть прототипы функций...передними нет не каких extern, а в моём проекте для at91sam7s128 компилятор требует (точнее линковщик)... в чём может быть разница????
Lotor
Цитата(Xeon @ Dec 22 2011, 13:01) *
Ну и там же для stm в проекте где есть прототипы функций...передними нет не каких extern

А для функций extern не обязателен. И это опять стандарт.
Xeon
Ну и ещё одно... разве стандарт С требует при объявлении глобальных переменных и функций в дразных модулях extern? help.gif

А вот об этом можете рассказать:
Тут же есть моментик... открываю проект для stm32чётотам ) и там нет ни каких extern...есть обычное объявление глобальных переменных в разных файлах и никаких руганьев компилятора или линковщика....

Компилятор один.... в чём разница... настройки сравнил все... всё одинаково, за исключением камня...
help.gif
Lotor
Цитата(Xeon @ Dec 22 2011, 13:06) *
Ну и ещё одно... разве стандарт С требует при объявлении глобальных переменных и функций в дразных модулях extern? help.gif

А вот об этом можете рассказать:
Тут же есть моментик... открываю проект для stm32чётотам ) и там нет ни каких extern...есть обычное объявление глобальных переменных в разных файлах и никаких руганьев компилятора или линковщика....

Компилятор один.... в чём разница... настройки сравнил все... всё одинаково, за исключением камня...
help.gif

По-моему Вам надо поучить матчасть. Это полезно. Стандарты за Вас никто читать не будет.

PS: погуглили бы прежде чем задавать такие вопросы. Одна из первых ссылок ответит Вам на все сумбурные вопросы http://www.rsdn.ru/forum/cpp/2706624.1.aspx
Xeon
Цитата(Lotor @ Dec 22 2011, 12:09) *
По-моему Вам надо поучить матчасть. Это полезно. Стандарты за Вас никто читать не будет.


А есть ссылочка на стандарт?)

Цитата(Lotor @ Dec 22 2011, 12:09) *
По-моему Вам надо поучить матчасть. Это полезно. Стандарты за Вас никто читать не будет.

PS: погуглили бы прежде чем задавать такие вопросы. Одна из первых ссылок ответит Вам на все сумбурные вопросы http://www.rsdn.ru/forum/cpp/2706624.1.aspx


Спасибо!)

А на примере той же visual studio, как там всё это дело работает, не вкурсе? Ведь там не надо писать подобного...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.