|
AT91SAM7X256 и Keil Vision 3V3.20a |
|
|
|
Mar 18 2008, 13:21
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Вот мой код: Использую Keil Vision 3V3.20a
#include <AT91SAM7X256.H> /* AT91SAMT7X256 definitions */ #include <lib_AT91SAM7X256.h> #include "Board.h" #define WAIT_TIME AT91B_MCK
#define PIO_INTERRUPT_LEVEL 6
void pio_c_irq_handler (void) __irq { int dummy; //* Read the output state if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOB) & AT91B_LED2 ) == AT91B_LED2 ) { AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, AT91B_LED2); } else { AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED2); } //* enable the next PIO IRQ dummy =AT91C_BASE_PIOA->PIO_ISR; //* suppress the compilation warning dummy =dummy; AT91C_BASE_AIC->AIC_EOICR=0x00;
//* while SW3 is push wait // while ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & AT91B_SW5 ) != AT91B_SW5 );
}
void delay ( void ) { volatile unsigned int i ;
for ( i = 0 ;(i < WAIT_TIME/100 );i++ ) ; }
//*---------------------------------------------------------------------------- //* Function Name : main //* Object : Main interrupt function //* Input Parameters : none //* Output Parameters : TRUE //*---------------------------------------------------------------------------- int main( void ) //* Begin { // unsigned int loop_count ; AT91PS_AIC pAic; //* Load System pAic Base address pAic = AT91C_BASE_AIC;
//* Init // loop_count = 0 ; // First, enable the clock of the PIOB AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOB ) ; AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA ) ; AT91F_PIO_CfgOutput( AT91C_BASE_PIOB, AT91B_LED_MASK ) ; AT91F_PIO_CfgInput(AT91C_BASE_PIOA, AT91B_SW5 | AT91B_SW4); AT91F_AIC_ConfigureIt ( pAic, AT91C_ID_PIOA, PIO_INTERRUPT_LEVEL,AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, pio_c_irq_handler); AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA,AT91B_SW4); AT91F_AIC_EnableIt (pAic, AT91C_ID_PIOA); AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED_MASK ) ;
for (;;) { AT91F_PIO_ClearOutput( AT91C_BASE_PIOB, AT91B_LED1 ); delay () ; AT91F_PIO_SetOutput( AT91C_BASE_PIOB, AT91B_LED1 ); delay () ;
}
//* End }
Вот мой Startup:
// Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
Mode_USR EQU 0x10 Mode_FIQ EQU 0x11 Mode_IRQ EQU 0x12 Mode_SVC EQU 0x13 Mode_ABT EQU 0x17 Mode_UND EQU 0x1B Mode_SYS EQU 0x1F
I_Bit EQU 0x80 /* when I bit is set, IRQ is disabled */ F_Bit EQU 0x40 /* when F bit is set, FIQ is disabled */
// Internal Memory Base Addresses FLASH_BASE EQU 0x00100000 RAM_BASE EQU 0x00200000
/* // <h> Stack Configuration (Stack Sizes in Bytes) // <o0> Undefined Mode <0x0-0xFFFFFFFF:4> // <o1> Supervisor Mode <0x0-0xFFFFFFFF:4> // <o2> Abort Mode <0x0-0xFFFFFFFF:4> // <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:4> // <o4> Interrupt Mode <0x0-0xFFFFFFFF:4> // <o5> User/System Mode <0x0-0xFFFFFFFF:4> // </h> */ UND_Stack_Size EQU 0x00000004 SVC_Stack_Size EQU 0x00000004 ABT_Stack_Size EQU 0x00000004 FIQ_Stack_Size EQU 0x00000004 IRQ_Stack_Size EQU 0x00000080 USR_Stack_Size EQU 0x00000400
AREA STACK, DATA, READWRITE, ALIGN=2 DS (USR_Stack_Size+3)&~3 ; Stack for User/System Mode DS (SVC_Stack_Size+3)&~3 ; Stack for Supervisor Mode DS (IRQ_Stack_Size+3)&~3 ; Stack for Interrupt Mode DS (FIQ_Stack_Size+3)&~3 ; Stack for Fast Interrupt Mode DS (ABT_Stack_Size+3)&~3 ; Stack for Abort Mode DS (UND_Stack_Size+3)&~3 ; Stack for Undefined Mode Top_Stack:
// Embedded Flash Controller (EFC) definitions EFC_BASE EQU 0xFFFFFF00 /* EFC Base Address */ EFC_FMR EQU 0x60 /* EFC_FMR Offset */
/* // <e> Embedded Flash Controller (EFC) // <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> // <i> Number of Master Clock Cycles in 1us // <o1.8..9> FWS: Flash Wait State // <0=> Read: 1 cycle / Write: 2 cycles // <1=> Read: 2 cycle / Write: 3 cycles // <2=> Read: 3 cycle / Write: 4 cycles // <3=> Read: 4 cycle / Write: 4 cycles // </e> */ EFC_SETUP EQU 1 EFC_FMR_Val EQU 0x00320100
// Watchdog Timer (WDT) definitions WDT_BASE EQU 0xFFFFFD40 /* WDT Base Address */ WDT_MR EQU 0x04 /* WDT_MR Offset */
/* // <e> Watchdog Timer (WDT) // <o1.0..11> WDV: Watchdog Counter Value <0-4095> // <o1.16..27> WDD: Watchdog Delta Value <0-4095> // <o1.12> WDFIEN: Watchdog Fault Interrupt Enable // <o1.13> WDRSTEN: Watchdog Reset Enable // <o1.14> WDRPROC: Watchdog Reset Processor // <o1.28> WDDBGHLT: Watchdog Debug Halt // <o1.29> WDIDLEHLT: Watchdog Idle Halt // <o1.15> WDDIS: Watchdog Disable // </e> */ WDT_SETUP EQU 1 WDT_MR_Val EQU 0x00008000
// Power Mangement Controller (PMC) definitions PMC_BASE EQU 0xFFFFFC00 /* PMC Base Address */ PMC_MOR EQU 0x20 /* PMC_MOR Offset */ PMC_MCFR EQU 0x24 /* PMC_MCFR Offset */ PMC_PLLR EQU 0x2C /* PMC_PLLR Offset */ PMC_MCKR EQU 0x30 /* PMC_MCKR Offset */ PMC_SR EQU 0x68 /* PMC_SR Offset */ PMC_MOSCEN EQU (1<<0) /* Main Oscillator Enable */ PMC_OSCBYPASS EQU (1<<1) /* Main Oscillator Bypass */ PMC_OSCOUNT EQU (0xFF<<8) /* Main OScillator Start-up Time */ PMC_DIV EQU (0xFF<<0) /* PLL Divider */ PMC_PLLCOUNT EQU (0x3F<<8) /* PLL Lock Counter */ PMC_OUT EQU (0x03<<14) /* PLL Clock Frequency Range */ PMC_MUL EQU (0x7FF<<16) /* PLL Multiplier */ PMC_USBDIV EQU (0x03<<28) /* USB Clock Divider */ PMC_CSS EQU (3<<0) /* Clock Source Selection */ PMC_PRES EQU (7<<2) /* Prescaler Selection */ PMC_MOSCS EQU (1<<0) /* Main Oscillator Stable */ PMC_LOCK EQU (1<<2) /* PLL Lock Status */
/* // <e> Power Mangement Controller (PMC) // <h> Main Oscillator // <o1.0> MOSCEN: Main Oscillator Enable // <o1.1> OSCBYPASS: Oscillator Bypass // <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255> // </h> // <h> Phase Locked Loop (PLL) // <o2.0..7> DIV: PLL Divider <0-255> // <o2.16..26> MUL: PLL Multiplier <0-2047> // <i> PLL Output is multiplied by MUL+1 // <o2.14..15> OUT: PLL Clock Frequency Range // <0=> 80..160MHz <1=> Reserved // <2=> 150..220MHz <3=> Reserved // <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63> // <o2.28..29> USBDIV: USB Clock Divider // <0=> None <1=> 2 <2=> 4 <3=> Reserved // </h> // <o3.0..1> CSS: Clock Source Selection // <0=> Slow Clock // <1=> Main Clock // <2=> Reserved // <3=> PLL Clock // <o3.2..4> PRES: Prescaler // <0=> None // <1=> Clock / 2 <2=> Clock / 4 // <3=> Clock / 8 <4=> Clock / 16 // <5=> Clock / 32 <6=> Clock / 64 // <7=> Reserved // </e> */ PMC_SETUP EQU 1 PMC_MOR_Val EQU 0x00000601 PMC_PLLR_Val EQU 0x00191C05 PMC_MCKR_Val EQU 0x00000007
$IF (RAM_INTVEC) // Exception Vector Area in RAM AREA VECTORS, DATA, AT RAM_BASE DS 64 $ENDIF
// Startup Code must be linked at address which it expects to run.
$IF (RAM_MODE) CODE_BASE EQU RAM_BASE $ELSE CODE_BASE EQU FLASH_BASE $ENDIF AREA STARTUPCODE, CODE, AT CODE_BASE PUBLIC __startup
EXTERN CODE32 (?C?INIT)
__startup PROC CODE32
// Pre-defined interrupt handlers that may be directly // overwritten by C interrupt functions EXTERN CODE32 (Undef_Handler?A) EXTERN CODE32 (SWI_Handler?A) EXTERN CODE32 (PAbt_Handler?A) EXTERN CODE32 (DAbt_Handler?A) ;EXTERN CODE32 (IRQ_Handler?A) ;EXTERN CODE32 (FIQ_Handler?A)
// Exception Vectors // Mapped to Address 0. // Absolute addressing mode must be used.
Vectors: LDR PC,Reset_Addr LDR PC,Undef_Addr LDR PC,SWI_Addr LDR PC,PAbt_Addr LDR PC,DAbt_Addr NOP /* Reserved Vector */ ; LDR PC,IRQ_Addr LDR PC,[PC,#-0xF20] /* Vector From AIC_IVR */ ; LDR PC,FIQ_Addr LDR PC,[PC,#-0xF20] /* Vector From AIC_FVR */
Reset_Addr: DD Reset_Handler Undef_Addr: DD Undef_Handler?A SWI_Addr: DD SWI_Handler?A PAbt_Addr: DD PAbt_Handler?A DAbt_Addr: DD DAbt_Handler?A DD 0 /* Reserved Address */ ;IRQ_Addr: DD IRQ_Handler?A IRQ_Addr: DD 0 ;FIQ_Addr: DD FIQ_Handler?A FIQ_Addr: DD 0
// Reset Handler
Reset_Handler:
// Setup EFC IF (EFC_SETUP != 0) LDR R0, =EFC_BASE LDR R1, =EFC_FMR_Val STR R1, [R0, #EFC_FMR] ENDIF
// Setup WDT IF (WDT_SETUP != 0) LDR R0, =WDT_BASE LDR R1, =WDT_MR_Val STR R1, [R0, #WDT_MR] ENDIF
// Setup PMC IF (PMC_SETUP != 0) LDR R0, =PMC_BASE
// Setup Main Oscillator LDR R1, =PMC_MOR_Val STR R1, [R0, #PMC_MOR]
// Wait until Main Oscillator is stablilized IF ((PMC_MOR_Val & PMC_MOSCEN) != 0) MOSCS_Loop: LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_MOSCS BEQ MOSCS_Loop ENDIF
// Setup the PLL IF ((PMC_PLLR_Val & PMC_MUL) != 0) LDR R1, =PMC_PLLR_Val STR R1, [R0, #PMC_PLLR]
// Wait until PLL is stabilized PLL_Loop: LDR R2, [R0, #PMC_SR] ANDS R2, R2, #PMC_LOCK BEQ PLL_Loop ENDIF
// Select Clock LDR R1, =PMC_MCKR_Val STR R1, [R0, #PMC_MCKR] ENDIF
// Copy Exception Vectors to Internal RAM
$IF (RAM_INTVEC) ADR R8, Vectors ; Source LDR R9, =RAM_BASE ; Destination LDMIA R8!, {R0-R7} ; Load Vectors STMIA R9!, {R0-R7} ; Store Vectors LDMIA R8!, {R0-R7} ; Load Handler Addresses STMIA R9!, {R0-R7} ; Store Handler Addresses $ENDIF
// Remap on-chip RAM to address 0
MC_BASE EQU 0xFFFFFF00 /* MC Base Address */ MC_RCR EQU 0x00 /* MC_RCR Offset */
$IF (REMAP) LDR R0, =MC_BASE MOV R1, #1 STR R1, [R0, #MC_RCR] ; Remap $ENDIF
// Setup Stack for each mode LDR R0, =Top_Stack
// Enter Undefined Instruction Mode and set its Stack Pointer MSR CPSR_c, #Mode_UND|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #UND_Stack_Size
// Enter Abort Mode and set its Stack Pointer MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #ABT_Stack_Size
// Enter FIQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #FIQ_Stack_Size
// Enter IRQ Mode and set its Stack Pointer MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #IRQ_Stack_Size
// Enter Supervisor Mode and set its Stack Pointer MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit MOV SP, R0 SUB R0, R0, #SVC_Stack_Size
// Enter User Mode and set its Stack Pointer MSR CPSR_c, #Mode_USR MOV SP, R0
// Enter the C code LDR R0,=?C?INIT TST R0,#1 ; Bit-0 set: main is Thumb LDREQ LR,=exit?A ; ARM Mode LDRNE LR,=exit?T ; Thumb Mode BX R0 ENDP
PUBLIC exit?A exit?A PROC CODE32 B exit?A ENDP
PUBLIC exit?T exit?T PROC CODE16 B exit?T ENDP
END
Компилирую, получаю hex-файл. С помощью HEX2BIN получаю бинарник. Гружу в плату AT91SAM7256-EK c помощью самбы. Стартую с 0x100000. Запускается. Мигает диодик. При нажатии джостика программа зависает, второй диод не загорается. В симуляторе (других отладчиков нет) все прекрасно работает. Прерывание отрабатывается и происходит возвращение в основной цикл. Почему не работает в железе? Пожалуйста, подскажите если кто знает.
|
|
|
|
|
Mar 18 2008, 14:01
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(aaarrr @ Mar 18 2008, 16:53)  Вы пытаетесь скопировать вектора прерываний в область ROM, что, естественно, не выходит. Сделайте Remap.
P.S. Пользуйтесь тегами [сode][/сode] - читать невозможно. Пожалуйста, можно подробнее? Где я пытаюсь скопировать вектор прерывания в область ROM и как сделать Remap. Я, знаете ли, только осваиваю технику и хочется быстро освоить.
|
|
|
|
|
Mar 18 2008, 14:10
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Limp @ Mar 18 2008, 17:01)  Пожалуйста, можно подробнее? Где я пытаюсь скопировать вектор прерывания в область ROM и как сделать Remap. Я, знаете ли, только осваиваю технику и хочется быстро освоить. Как выяснилось, даже не пытаетесь копировать  Вам нужно добавить строки: Код RAM_INTVEC EQU 1 REMAP EQU 1 в начале startup'а. После remap'а SRAM встанет по нулевому адресу, и вектора окажутся на своем месте.
|
|
|
|
|
Mar 19 2008, 08:14
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(aaarrr @ Mar 18 2008, 17:10)  Как выяснилось, даже не пытаетесь копировать  Вам нужно добавить строки: Код RAM_INTVEC EQU 1 REMAP EQU 1 в начале startup'а. После remap'а SRAM встанет по нулевому адресу, и вектора окажутся на своем месте. Не знаю как Вас благодарить!!! Огромное СПАСИБО!!! Заработало!!!
|
|
|
|
|
Mar 20 2008, 13:42
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
У меня опять проблема. Делаю на плате кнопочкой RESET. Программа перестает работать. В изложенную выше программу в main() добавил функцию: AT91C_BASE_RSTC->RSTC_RMR = AT91C_RSTC_URSTEN |(0x4<<8) | (unsigned int)(0xA5<<24); Или опять проблема с Startup? По идее программа после ресета должна заработать снова, ведь прерывания отрабатываются.
|
|
|
|
|
Mar 20 2008, 13:56
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(aaarrr @ Mar 20 2008, 16:52)  А GPNVM2 в Самбе запрограммировать не забыли? Забыл, потому что первый раз слышу о GPNVM2 в Самбе. Намекните с чем ее едят?
|
|
|
|
|
Mar 21 2008, 05:46
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(aaarrr @ Mar 20 2008, 17:33)  Внизу есть окошко "scripts", в нем на первом месте стоит "Boot from Flash (GPNVM2)" - его и нужно выполнить. А так у Вас процессор стартует из ROM по сбросу. И снова БОЛЬШОЕ Вам спасибо!!! Вы мне очень помогли!!! В моей доке о SAMBA нет ни слова о "Boot from Flash (GPNVM2)". Еще раз спасибо!!! Но тут происходит интересный момент по сбросу программа сразу же вылетает в обработчик прерывания void pio_c_irq_handler (void) __irq. Очевидно по сбросу ловит перепад на PIOA.
|
|
|
|
|
Mar 21 2008, 09:37
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(aaarrr @ Mar 21 2008, 11:31)  Это вполне возможно. Прерывание лучше сбрасывать непосредственно перед разрешением. Блогадарю Вас за поддержку. С этим я уже разобрался. Разбираюсь дальше. Думаю, что вопросы еще у меня возникнут и надеюсь, что Вы в дальнейшем мне поможите своими советами. Спасибо!
|
|
|
|
|
Mar 28 2008, 08:28
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
От чего так происходит? Плата подключена к компу через DBGU. (AT91SAM7X256-EK) Собственно обмен происходит, как из компа в плату так из платы в комп. Но вот в основном цикле платы надо послать 4 байта подряд в комп:
AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
AT91C_BASE_DBGU->DBGU_THR = 0x54;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
AT91C_BASE_DBGU->DBGU_THR = 0x0D;
В компе принимается один или два байта. Два байта пропадают? Почему? Когда после операторов while ставлю задержку, например, delay (), комп принимает все четыре байта. Скорость передачи как для платы, так и для компа 115200. При этом при передаче данных из компа в плату нескольких байт подряд проблем нет, прием данных производится в обработчике прерывания приемника DBGU. В обработчике прерываний при передаче из платы в комп ни чего не делаю, просто вываливаюсь, предварительно произведя AT91C_BASE_AIC->AIC_EOICR=0x00;
|
|
|
|
|
Mar 28 2008, 08:39
|
Участник

Группа: Участник
Сообщений: 26
Регистрация: 7-02-06
Из: Зеленоград
Пользователь №: 14 071

|
Цитата(Limp @ Mar 28 2008, 11:28)  От чего так происходит? Плата подключена к компу через DBGU. (AT91SAM7X256-EK) Собственно обмен происходит, как из компа в плату так из платы в комп. Но вот в основном цикле платы надо послать 4 байта подряд в комп:
AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
AT91C_BASE_DBGU->DBGU_THR = 0x54;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) AT91C_BASE_DBGU->DBGU_THR = 0x41;
while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY))
AT91C_BASE_DBGU->DBGU_THR = 0x0D;
В компе принимается один или два байта. Два байта пропадают? Почему? Когда после операторов while ставлю задержку, например, delay (), комп принимает все четыре байта. Скорость передачи как для платы, так и для компа 115200. При этом при передаче данных из компа в плату нескольких байт подряд проблем нет, прием данных производится в обработчике прерывания приемника DBGU. В обработчике прерываний при передаче из платы в комп ни чего не делаю, просто вываливаюсь, предварительно произведя AT91C_BASE_AIC->AIC_EOICR=0x00; После while(...) надо точку с запятой ставить  Вот так: Код while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)); А то у Вас получается следующий код: Код AT91C_BASE_DBGU->DBGU_THR = 0x41; while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x54; } while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x41; } while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x0D; } Удачи!
Сообщение отредактировал ljerry - Mar 28 2008, 08:42
|
|
|
|
|
Mar 28 2008, 08:47
|
Участник

Группа: Участник
Сообщений: 49
Регистрация: 6-02-08
Пользователь №: 34 796

|
Цитата(ljerry @ Mar 28 2008, 11:39)  После while(...) надо точку с запятой ставить  Вот так: Код while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)); А то у Вас получается следующий код: Код AT91C_BASE_DBGU->DBGU_THR = 0x41; while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x54; } while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x41; } while (!(AT91C_BASE_DBGU->DBGU_CSR &AT91C_US_TXRDY)) { AT91C_BASE_DBGU->DBGU_THR = 0x0D; } Удачи! Надо же, как меня перемкнуло!!! Надо отвлекаться иногда.... СПАСИБО!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|