реклама на сайте
подробности

 
 
> Возможность использования OS::channel в прерываниях
abutorin
сообщение Jan 13 2013, 19:25
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Добрый вечер.
Пробую сделать передачу по USART с использование буфера. Для межпроцессорного удобства очень нравится использовать OS::channel. Возможно ли его использовать и в прерываниях? Точнее интересует процедура получения элемента из канала?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
AHTOXA
сообщение Jan 13 2013, 20:45
Сообщение #2


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Использовать канал в прерывании можно. Учтите только, что если вы в него что-то заталкиваете, а он полон, то будет сделана попытка усыпить прерванный процесс и дождаться освобождения (или при доставании из пустого канала). Вероятно, это не то поведение, которое ожидается в прерыванииsm.gif
Поэтому проверяйте наличие свободного места при запихивании чего-то в канал, и наличие данных при доставании из канала.
Примерно вот так:
Код
void uart_t::irq_handler(){
    uint16_t status = USARTx->SR;
    if (status & USART_SR_RXNE){
        uint8_t ch = USARTx->DR;
        if (RxChannel.get_free_size())
            RxChannel.push(ch);
    }
            
    if (status & USART_SR_TXE){
        if (TxChannel.get_count()){
            char ch = 0;
            TxChannel.pop(ch);
            USARTx->DR = ch;
        }
        else
            disable_tx_interrupt();
    }
}


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 15 2013, 19:16
Сообщение #3


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(AHTOXA @ Jan 14 2013, 00:45) *
Использовать канал в прерывании можно. Учтите только, что если вы в него что-то заталкиваете, а он полон, то будет сделана попытка усыпить прерванный процесс и дождаться освобождения (или при доставании из пустого канала). Вероятно, это не то поведение, которое ожидается в прерыванииsm.gif
Поэтому проверяйте наличие свободного места при запихивании чего-то в канал, и наличие данных при доставании из канала.


Примерно так и делал.
Код
    
class usart_t
{
public:
    OS::channel<uint8_t,4> Rxbuf;
    OS::channel<uint8_t,4> Txbuf;
    USART_TypeDef * PORT;

INLINE void it_handler ()
    {

        if (USART_GetITStatus(this->PORT,USART_IT_TXE) != RESET)
        {
            {
                if(this->Txbuf.get_count())
                {
                    uint8_t data;
                    this->Txbuf.pop(data);
                    USART_SendData(this->PORT,data);
                }
                else
                {
                    USART_ITConfig(this->PORT, USART_IT_TXE, DISABLE);
                }

            }

            USART_ClearITPendingBit(this->PORT,USART_IT_TXE);
        }

    }

    void send(const uint8_t & data)
    {
        this->Txbuf.push(data);
        USART_ITConfig(this->PORT, USART_IT_TXE, ENABLE);

    }


Размер буфера 4 элемента. заполняю его в одном из потоков:
Код
        
      for(i=0;i<8;i++)
        {
            usart.send(i+0x30);
        }

        OS::sleep(1000);

Задача проверить работоспособность при заполнении буфера до отказа. В результата камень зависает в прерывании. Причем смотрю терминалом на компьютере, нормально отправляется только 2 байта.

Поэкспериментировал немного с размером буфера и размером отправляемых данных, если размер буфера поставить 5 и отправлять 8 байт то все работает нормально, размер буфера 14 количество отправляемых данных 16 тоже нормально. На лицо правило размер буфера = количество отправляемых данных - 2.

Сообщение отредактировал abutorin - Jan 15 2013, 19:03
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 15 2013, 19:26
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Не знаю почему зависает, наверное что-то неправильно ...
Не пойму, в чём сермяга посать всюду this->?
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 15 2013, 19:31
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(_Артём_ @ Jan 15 2013, 23:26) *
Не знаю почему зависает, наверное что-то неправильно ...
Не пойму, в чём сермяга посать всюду this->?

Объектный подход, да можно былобы статичным класом обойтись, думаю это не критично.

Посмотрел поглубже, помоему нашел в чем проблема:
Код
template<typename T, uint16_t Size, typename S>
void OS::channel<T, Size, S>::push(const T& item)
{
    TCritSect cs;

    while(!pool.get_free_size())
    {
        // channel is full, suspend current process until data removed
        suspend(ProducersProcessMap);
    }

    pool.push_back(item);
    resume_all(ConsumersProcessMap);
}

Судя по коду, push выполняется с запретом прерывания. Как я понимаю работу TCritSect, запрет снимается в деструкторе, так вот деструктор не вызовется, т.к. потребитель канала находится в прерывании.
Получается что канал использовать с прерываниями не получится.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 15 2013, 22:46
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (abutorin @ Jan 15 2013, 21:31) *
Судя по коду, push выполняется с запретом прерывания. Как я понимаю работу TCritSect, запрет снимается в деструкторе, так вот деструктор не вызовется, т.к. потребитель канала находится в прерывании.
Прерывания будут разрешены во время suspend() при передаче управления другому процессу. Что касается вашей проблемы - мне кажется причина в том, что вы делаете USART_ClearITPendingBit(this->PORT,USART_IT_TXE); даже если данных не было и ничего не было передано. И когда данные в канале появляются - у процессора нет причин вызвать прерывание и отправить их. Хотя я не очень хорошо помню, как этот механизм (pending) работает в кортексах. Также полагаю, что объект типа OS::TCritSect вы в начале обработчика прерывания создаете. Если нет - это тоже может быть причиной.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 16 2013, 03:29
Сообщение #7


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(Сергей Борщ @ Jan 16 2013, 02:46) *
Прерывания будут разрешены во время suspend() при передаче управления другому процессу. Что касается вашей проблемы - мне кажется причина в том, что вы делаете USART_ClearITPendingBit(this->PORT,USART_IT_TXE); даже если данных не было и ничего не было передано. И когда данные в канале появляются - у процессора нет причин вызвать прерывание и отправить их. Хотя я не очень хорошо помню, как этот механизм (pending) работает в кортексах. Также полагаю, что объект типа OS::TCritSect вы в начале обработчика прерывания создаете. Если нет - это тоже может быть причиной.

USART_ClearITPendingBit(this->PORT,USART_IT_TXE); Это очистка признака возникновения прерывания, в у STM32 большинство битов (признаков) прерывания необходимо очищать вручную. Прерывание по USART_IT_TXE выключается командой USART_ITConfig(this->PORT, USART_IT_TXE, DISABLE); только в случае если канал пустой. А в процедуре которая заполняет канал send это прерывание всегда включаетсся.
USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

Посмотрел еще раз
Код
   void OS::TService::suspend(TProcessMap volatile & waiters_map)
    {
        TProcessMap PrioTag = cur_proc_prio_tag();
    
        set_prio_tag(waiters_map, PrioTag);                   // put current process to wait map
        clr_prio_tag(ready_process_map(), PrioTag);           // remove current process from ready map
    
    #if scmRTOS_DEBUG_ENABLE == 1
        cur_proc_waiting_for() = this;                        // catch current service address to process debug data
    #endif

    #if scmRTOS_PROCESS_RESTART_ENABLE == 1
        cur_proc_waiting_map() = &waiters_map;
    #endif
        
        reschedule();
        
    #if scmRTOS_DEBUG_ENABLE == 1
        cur_proc_waiting_for() = 0;                           // remove current service address from process debug data
    #endif
        
    #if scmRTOS_PROCESS_RESTART_ENABLE == 1
        cur_proc_waiting_map() = 0;
    #endif
        
    }

void OS::channel<T, Size, S>::push(const T& item)
{
    TCritSect cs;

    while(!pool.get_free_size())
    {
        // channel is full, suspend current process until data removed
        suspend(ProducersProcessMap);
    }

    pool.push_back(item);
    resume_all(ConsumersProcessMap);
}

А в какой момент происходи включение прерываний? в suspend я не нашел включение прерываний.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 16 2013, 08:54
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (abutorin @ Jan 16 2013, 05:29) *
USART_ClearITPendingBit(this->PORT,USART_IT_TXE); Это очистка признака возникновения прерывания, в у STM32 большинство битов (признаков) прерывания необходимо очищать вручную.
К сожалению я использую для передачи DMA, поэтому у меня нет примера для UART c каналом. Без ОС рабочий код у меня выглядит так:
CODE
INLINE void uart::handler()
{
    uint32_t Status = pUART->SR;
    Status &= pUART->CR1;   // mask disabled ints

    if(Status & USART_SR_RXNE)
    {
        uint8_t Data = pUART->DR;
        if(Rx_buffer.has_place())
            Rx_buffer.put(Data);
    }
    if(Status & USART_SR_TXE)
    {
        pUART->DR = Tx_buffer.get();
        if(!Tx_buffer.has_data())
            pUART->CR1 &= ~USART_CR1_TXEIE;
    }
}
Как видите, никаких ручных очисток.


QUOTE (abutorin @ Jan 16 2013, 05:29) *
А в какой момент происходи включение прерываний? в suspend я не нашел включение прерываний.
Из suspend() вызывается TKernelAgent::reschelule(), который в свою очередь вызывет TKernel::shed(), в котором есть такой код:
CODE
        do
        {
            enable_context_switch();
            DUMMY_INSTR();
            disable_context_switch();
        }
        while(CurProcPriority != SchedProcPriority); // until context switch done
Вот тут произойдет переключение на другой процесс, а уже этот процесс (если нет активных - то процесс Idle) выполняется с разрешенными прерываниями, т.е. при восстановлении его контекста прерывания будут разрешены.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
abutorin
сообщение Jan 16 2013, 11:33
Сообщение #9


Участник
*

Группа: Участник
Сообщений: 40
Регистрация: 3-09-12
Пользователь №: 73 374



Цитата(Сергей Борщ @ Jan 16 2013, 12:54) *
К сожалению я использую для передачи DMA, поэтому у меня нет примера для UART c каналом.

У меня логика построена на том, что я с уартом работаю как с потоком байт, я не знаю сколько байт отправляюи сколько получу. Если даже с таким подходом это можно реализовать через DMA то был бы очень признателен за пример.
Если с прерываниями стало ясно.то опять возникает вопрос в чем же тогда проблема?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 17 2013, 10:15
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (abutorin @ Jan 16 2013, 13:33) *
Если с прерываниями стало ясно.то опять возникает вопрос в чем же тогда проблема?
Вы заводите в начале обработчика объект типа OS::TISRW (я в предыдущем сообщении описался, указав его как OS::TCritSect)? Без него прерывание не сможет при необходимости вызвать перепланирование.

QUOTE (abutorin @ Jan 16 2013, 13:33) *
У меня логика построена на том, что я с уартом работаю как с потоком байт, я не знаю сколько байт отправляюи сколько получу. Если даже с таким подходом это можно реализовать через DMA то был бы очень признателен за пример.
Как-то так, хотя мне самому этот код не очень нравится:
CODE

//**** uart.h: *****
#ifndef UART_H__
#define UART_H__
#include <stdint.h>
#include <stm32f10x.h>
#include <scmRTOS.h>
#include <string.h>

#include <stdarg.h>
#include <stdio.h>

class uart
{
public:
uart(USART_TypeDef * usart, uint32_t dma_channel)
: Tx_ready(OS::TEventFlag::efOn)
, pUART(usart)
, DMA_channel_no(dma_channel - 1)
, DMA_channel((DMA_Channel_TypeDef *)(DMA1_Channel1_BASE + (dma_channel - 1) * 0x14))
{}

void send(const uint8_t &byte);
void send(char const * string);
void send(char * string, OS::TMutex * pLock);
void send_HEX(uint8_t data);
void send_HEX(uint16_t data);
void new_line();
void vprintf(char const * format, va_list args);
void printf(char const * format, ...);
bool is_transmitting() {return !(pUART->SR & USART_SR_TXE);}

bool hasinput() {return Rx_buffer.get_count();}
bool receive(uint8_t & data, timeout_t timeout);
bool receive(char & data, timeout_t timeout);
uint8_t receive() { uint8_t Data; Rx_buffer.pop(Data); return Data;}

void speed_setup(uint_fast32_t baudrate) { pUART->BRR = (PCLK1_FREQ + baudrate / 2) / baudrate; }
void tx_dma_handler();
void rx_handler();
protected:
static size_t const RX_BUFF_SIZE = 16;

OS::TEventFlag Tx_ready;
uint8_t Tx_byte_buffer;
OS::TMutex Tx_byte_buffer_lock;

OS::TMutex Tx_buffer_lock;
char Tx_buffer[80];

OS::TMutex * pDMA_buffer_lock;
void setup_tx_dma(uint8_t const * pSrc, size_t size, OS::TMutex *pLock = 0);

OS::channel<uint8_t volatile, RX_BUFF_SIZE> Rx_buffer;
private:
USART_TypeDef * pUART;
uint_fast32_t DMA_channel_no;
DMA_Channel_TypeDef * DMA_channel;
};
// =========== receiving ==============
INLINE void uart::rx_handler()
{
uint8_t Data = pUART->DR;
if(Rx_buffer.get_free_size())
Rx_buffer.push(Data);
}

inline bool uart::receive(uint8_t & symbol, timeout_t timeout)
{
if(timeout <= 0 || !Rx_buffer.pop(symbol, timeout))
return false;
return true;
}

inline bool uart::receive(char & symbol, timeout_t timeout)
{
uint8_t data;
if(timeout <= 0 || !Rx_buffer.pop(data, timeout))
return false;
symbol = char(data);
return true;
}

// ========== transmitting ===========

INLINE void uart::tx_dma_handler()
{
DMA1->IFCR = DMA_IFCR_CTCIF1 << (4 * DMA_channel_no);
DMA_channel->CCR = 0
;
Tx_ready.signal_isr();
if(pDMA_buffer_lock)
pDMA_buffer_lock->unlock_isr();
}

#endif //UART_H__


//**** uart.cpp ******
#include "uart.h"
#include <string.h>

void uart::setup_tx_dma(uint8_t const * pSrc, size_t size, OS::TMutex * pLock)
{
Tx_ready.wait();
pDMA_buffer_lock = pLock;
// --------- DMA setup -----------
DMA_channel->CPAR = uintptr_t(&pUART->DR);
DMA_channel->CMAR = uintptr_t(pSrc);
DMA_channel->CNDTR = size;
DMA_channel->CCR = 0
| 1 * DMA_CCR1_EN // Channel enable
| 1 * DMA_CCR1_TCIE // Transfer complete interrupt enable
| 0 * DMA_CCR1_HTIE // Half Transfer interrupt enable
| 0 * DMA_CCR1_TEIE // Transfer error interrupt enable
| 1 * DMA_CCR1_DIR // Data transfer direction: Memory->Peripheral
| 0 * DMA_CCR1_CIRC // Circular mode
| 0 * DMA_CCR1_PINC // Peripheral increment mode
| 1 * DMA_CCR1_MINC // Memory increment mode
| 0 * DMA_CCR1_PSIZE_0 // Peripheral size: 8 bits
| 0 * DMA_CCR1_MSIZE_0 // Memory size: 8 bits
| 1 * DMA_CCR1_PL_0 // Channel Priority level: higher than lowest, conversion frequency is low enough
| 0 * DMA_CCR1_MEM2MEM // Memory to memory mode disabled
;

}

void uart::send(uint8_t const &byte)
{
Tx_byte_buffer_lock.lock();
Tx_byte_buffer = byte;
setup_tx_dma(&Tx_byte_buffer, 1, &Tx_byte_buffer_lock);
}

void uart::send(char const * pString)
{
setup_tx_dma((uint8_t const *)pString, strlen(pString));
}

void uart::send(char * pString, OS::TMutex * pLock)
{
setup_tx_dma((uint8_t const *)pString, strlen(pString), pLock);
}

void uart::vprintf(char const * format, va_list args)
{

Tx_buffer_lock.lock();
vsprintf (Tx_buffer, format, args);
send(Tx_buffer, &Tx_buffer_lock);
}

void uart::printf(char const * format, ...)
{
va_list args;
va_start (args, format);
uart::vprintf (format, args);
va_end (args);
}


uart Serial(USART2, 7);
uart & Console = Serial;


extern "C" void DMA1_Channel7_IRQHandler(void)
{
OS::TISRW ISR_wrapper;
Console.tx_dma_handler();
}

extern "C" void USART2_IRQHandler(void)
{
OS::TISRW ISR_wrapper;
Console.rx_handler();
}

Тут готовность DMA передается через флаг Tx_ready, а буфер передачи (если он используется для данной посылки) защищен мутексом Tx_byte_buffer_lock. Если же передается готовая строка из флеша или ОЗУ - буфер не используется.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- abutorin   Возможность использования OS::channel в прерываниях   Jan 13 2013, 19:25
|- - abutorin   Спасибо, проверку заполнености, проверку пустоты я...   Jan 14 2013, 02:40
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 21:31) Объ...   Jan 15 2013, 20:10
|- - _Артём_   Цитата(abutorin @ Jan 16 2013, 05:29) А в...   Jan 16 2013, 04:45
||- - AHTOXA   TXE очищается записью в DR. Вручную его чистить не...   Jan 16 2013, 05:05
|- - AHTOXA   Цитата(Сергей Борщ @ Jan 16 2013, 14:54) ...   Jan 16 2013, 10:18
||- - Сергей Борщ   QUOTE (AHTOXA @ Jan 16 2013, 12:18) А это...   Jan 16 2013, 11:27
||- - AHTOXA   Цитата(Сергей Борщ @ Jan 16 2013, 17:27) ...   Jan 16 2013, 13:52
|- - abutorin   Цитата(Сергей Борщ @ Jan 17 2013, 14:15) ...   Jan 17 2013, 12:25
|- - Сергей Борщ   QUOTE (abutorin @ Jan 17 2013, 14:25) Пло...   Jan 17 2013, 13:12
|- - abutorin   Цитата(Сергей Борщ @ Jan 17 2013, 17:12) ...   Jan 17 2013, 13:20
|- - AHTOXA   Насчёт работы с UART по DMA вот вам три темы: раз...   Jan 17 2013, 18:31
|- - abutorin   Цитата(AHTOXA @ Jan 17 2013, 22:31) Насчё...   Jan 18 2013, 05:37
|- - Сергей Борщ   QUOTE (abutorin @ Jan 18 2013, 07:37) Спа...   Jan 18 2013, 07:41
|- - abutorin   Цитата(Сергей Борщ @ Jan 18 2013, 11:41) ...   Jan 18 2013, 09:14
- - Vasya777   Мне кажется для обмена по интерфейсам связи лучше ...   Jan 15 2013, 15:07
- - abutorin   Проблему решил использовав События: Кодclass usart...   Jan 15 2013, 20:14
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 22:14) есл...   Jan 15 2013, 20:20
|- - abutorin   Цитата(_Артём_ @ Jan 16 2013, 00:20) На ч...   Jan 15 2013, 20:24
|- - _Артём_   Цитата(abutorin @ Jan 15 2013, 22:24) Вто...   Jan 15 2013, 20:52
- - abutorin   Как обещал ранее выкладываю код который у меня раб...   Jan 18 2013, 18:52
|- - AHTOXA   USART_ClearITPendingBit(this->PORT,USART_IT_TXE...   Jan 19 2013, 04:43
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 08:43) USART...   Jan 19 2013, 17:19
|- - AHTOXA   Цитата(abutorin @ Jan 19 2013, 23:19) В к...   Jan 19 2013, 17:42
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 21:42) Код ...   Jan 19 2013, 17:56
||- - _Артём_   Цитата(abutorin @ Jan 19 2013, 19:56) В с...   Jan 19 2013, 18:13
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 21:42) Код ...   Jan 19 2013, 18:42
|- - AHTOXA   Цитата(abutorin @ Jan 20 2013, 00:42) С т...   Jan 19 2013, 19:12
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 23:12) У мен...   Jan 19 2013, 19:19
|- - AHTOXA   Насчёт компактности - думаю, что случайно так вышл...   Jan 19 2013, 19:36
|- - abutorin   Цитата(AHTOXA @ Jan 19 2013, 23:36) А по ...   Jan 19 2013, 20:01
|- - AHTOXA   Цитата(abutorin @ Jan 20 2013, 02:01) Есл...   Jan 19 2013, 20:21
|- - abutorin   Цитата(AHTOXA @ Jan 20 2013, 00:21) А уве...   Jan 19 2013, 20:42
|- - AHTOXA   Ну, с тех пор что-то же поменялось. Так что это бы...   Jan 20 2013, 05:31
|- - abutorin   Цитата(AHTOXA @ Jan 20 2013, 09:31) В общ...   Jan 20 2013, 05:57
- - сарматъ   я так и не понял, а функции типа push_isr() не нуж...   Sep 4 2013, 20:26
|- - _Артём_   Цитата(сарматъ @ Sep 4 2013, 23:26) я так...   Sep 4 2013, 21:41
|- - сарматъ   там могло бы быть что либо такого плана CODEtempl...   Sep 5 2013, 05:39
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 07:39) там м...   Sep 5 2013, 06:10
- - сарматъ   да я уже подумал над этим правда придется не насле...   Sep 5 2013, 06:24
|- - dxp   QUOTE (сарматъ @ Sep 5 2013, 13:24) да я ...   Sep 5 2013, 07:21
|- - сарматъ   потому что нужен вот такой вот пул и если я его до...   Sep 5 2013, 07:37
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 09:37) потом...   Sep 5 2013, 08:25
- - сарматъ   да, класс канала отличный класс, плюс ко всем его ...   Sep 5 2013, 08:33
|- - Сергей Борщ   QUOTE (сарматъ @ Sep 5 2013, 10:33) сдела...   Sep 6 2013, 08:29
- - сарматъ   ок, так и сделаю и потом выложу сюда что получилос...   Sep 6 2013, 08:44


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd June 2025 - 15:50
Рейтинг@Mail.ru


Страница сгенерированна за 0.01605 секунд с 7
ELECTRONIX ©2004-2016