5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
1

Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?

12.10.2021, 18:05. Показов 1770. Ответов 32
Метки нет (Все метки)

При тестировании обнаружил, что при определенных обстоятельствах происходит HardFault_Handler. Проблема происходит всегда когда я делаю определенное действие. В общем это выглядит так: Есть проект в котором есть STM32F103 и NRF24L01 между ними есть коммуникация. Один дивайс настраивается как передачик, второй как приемник. Когда приемник принимает данные температуры и влажности от передатчика, и, когда я выхожу из конкретного меню, то дивайс который принимает данные, зависает и переходит в HardFault_Handler. Данный баг воспроизводится на обоих дивайсах, на которых можно менять роли предавача и приемника. Но данный баг не отображается если передавать просто тестовые данные (счетчик).
0
Миниатюры
Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?   Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?  
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.10.2021, 18:05
Ответы с готовыми решениями:

Запуск Excel из Access происходит строго периодически - через раз происходит сбой
запуск Excell из Access происходит строго периодически - через раз. происходит сбой. После сбоя...

Написать функцию, при выполнении которой происходит построение однополостного гиперболоида
Доброго времени суток. Нужно написать функцию, при выполнении которой происходит построение...

Напишите функцию Города(), при запуске которой происходит заполнение двух списков
Напишите функцию Города(), при запуске которой происходит заполнение двух списков: города, жители....

Напишите функцию допуск(), при запуске которой происходит заполнение двух списков
Напишите функцию допуск(), при запуске которой происходит заполнение двух списков: абитуриенты,...

32
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
12.10.2021, 21:10  [ТС] 2
перед тем как зависнуть в HardFault_Handler я вижу такую картину
0
Миниатюры
Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?  
Почетный модератор
11236 / 4189 / 420
Регистрация: 12.06.2008
Сообщений: 12,082
12.10.2021, 22:24 3
На первом скриншоте слева показано, как он в функции заходил. Видно, что из какой-то I2C_WaitOnBT..... он перешёл на адрес 0x61000000, а т.к. этот адрес, скорее всего, несущетсвующий, то оттуда процессор улетел в исключение. Надо смотреть эту функцию и думать, почему оттуда идёт переход по этому адресу. Возможно, там вызвается какой-нибудь колбек, который не был инициализирован.
1
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
12.10.2021, 22:53 4
Ещё можно посмотреть в отладочных регистрах ядра. Иногда можно в них найти точное место ошибки и её причины.
1
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
13.10.2021, 14:24  [ТС] 5
Цитата Сообщение от Rius Посмотреть сообщение
Ещё можно посмотреть в отладочных регистрах ядра. Иногда можно в них найти точное место ошибки и её причины.
Регистр pc как я понимаю показывает на функцию в которой работает сейчас мк.
До вилюота регистр pc показывал функцию 0x80044fe <nrf_rx_mode+166>.
Потом на pc показывал 0x100000
Потом Error
Потом на 0x8003276 <HardFault_Handler>
0
Миниатюры
Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?   Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?   Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?  

Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?  
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
13.10.2021, 17:05 6
OlegD_STM32, Debug регистры это не pc, а нечто совсем иное. Описаны в reference manual на ядро.
Регистры CFSR, UFSR, BFSR, и всё что там ещё найдёте.
Cortex-M3 Devices Generic User Guide
How to debug a HardFault on an ARM Cortex-M MCU
Что делать, если поймал HardFault?
0
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
13.10.2021, 19:26  [ТС] 7
Цитата Сообщение от Rius Посмотреть сообщение
Регистры CFSR, UFSR, BFSR, и всё что там ещё найдёте.
Cortex-M3 Devices Generic User Guide
это не эти регистры с права, вдокументации?
Видно что бит PRECISERR установлен, но, что он означает, и что делать дальше я не понимаю
0
Миниатюры
Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?   Проваливается в HardFault_Handler Как узнать функцию/инструкцию по которой происходит сбой?  
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
13.10.2021, 19:47 8
Они. А что за среда разработки?
Адрес проблемной инструкции должен быть в BFAR.

Добавлено через 2 минуты
Он уже выведен: 0x22E6F0.
0
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
13.10.2021, 19:47  [ТС] 9
Цитата Сообщение от Rius Посмотреть сообщение
Они. А что за среда разработки?
STM32IDE
1
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
13.10.2021, 19:47 10
Теперь надо файл LST открыть и посмотреть, что там находится по этому адресу.
0
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
13.10.2021, 21:18  [ТС] 11
Цитата Сообщение от Rius Посмотреть сообщение
Теперь надо файл LST открыть и посмотреть, что там находится по этому адресу.
в проекте нашел файл NRF_and_LoRa_RX.list, но в нем я не нашел инструкции по адресу 0x22E6F0.

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
NRF_and_LoRa_RX.elf:     file format elf32-littlearm
 
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .isr_vector   0000010c  08000000  08000000  00010000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .text         00008e5c  0800010c  0800010c  0001010c  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  2 .rodata       000009e4  08008f68  08008f68  00018f68  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .ARM.extab    00000000  0800994c  0800994c  000200b4  2**0
                  CONTENTS
  4 .ARM          00000000  0800994c  0800994c  000200b4  2**0
                  CONTENTS
  5 .preinit_array 00000000  0800994c  0800994c  000200b4  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  6 .init_array   00000004  0800994c  0800994c  0001994c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  7 .fini_array   00000004  08009950  08009950  00019950  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  8 .data         000000b4  20000000  08009954  00020000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  9 .bss          00000988  200000b4  08009a08  000200b4  2**2
                  ALLOC
 10 ._user_heap_stack 00000604  20000a3c  08009a08  00020a3c  2**0
                  ALLOC
 11 .ARM.attributes 00000029  00000000  00000000  000200b4  2**0
                  CONTENTS, READONLY
 12 .debug_info   00018871  00000000  00000000  000200dd  2**0
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 13 .debug_abbrev 0000330d  00000000  00000000  0003894e  2**0
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 14 .debug_aranges 000013d8  00000000  00000000  0003bc60  2**3
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 15 .debug_ranges 000012c0  00000000  00000000  0003d038  2**3
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 16 .debug_macro  00019bed  00000000  00000000  0003e2f8  2**0
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 17 .debug_line   00018e40  00000000  00000000  00057ee5  2**0
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 18 .debug_str    000906a6  00000000  00000000  00070d25  2**0
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 19 .comment      00000053  00000000  00000000  001013cb  2**0
                  CONTENTS, READONLY
 20 .debug_frame  00005934  00000000  00000000  00101420  2**2
                  CONTENTS, READONLY, DEBUGGING, OCTETS
 
Disassembly of section .text:
 
0800010c <__do_global_dtors_aux>:
 800010c:   b510        push    {r4, lr}
 800010e:   4c05        ldr r4, [pc, #20]   ; (8000124 <__do_global_dtors_aux+0x18>)
 8000110:   7823        ldrb    r3, [r4, #0]
 8000112:   b933        cbnz    r3, 8000122 <__do_global_dtors_aux+0x16>
 8000114:   4b04        ldr r3, [pc, #16]   ; (8000128 <__do_global_dtors_aux+0x1c>)
 8000116:   b113        cbz r3, 800011e <__do_global_dtors_aux+0x12>
 8000118:   4804        ldr r0, [pc, #16]   ; (800012c <__do_global_dtors_aux+0x20>)
 800011a:   f3af 8000   nop.w
 800011e:   2301        movs    r3, #1
 8000120:   7023        strb    r3, [r4, #0]
 8000122:   bd10        pop {r4, pc}
 8000124:   200000b4    .word   0x200000b4
 8000128:   00000000    .word   0x00000000
 800012c:   08008f50    .word   0x08008f50
 
08000130 <frame_dummy>:
 8000130:   b508        push    {r3, lr}
 8000132:   4b03        ldr r3, [pc, #12]   ; (8000140 <frame_dummy+0x10>)
 8000134:   b11b        cbz r3, 800013e <frame_dummy+0xe>
 8000136:   4903        ldr r1, [pc, #12]   ; (8000144 <frame_dummy+0x14>)
 8000138:   4803        ldr r0, [pc, #12]   ; (8000148 <frame_dummy+0x18>)
 800013a:   f3af 8000   nop.w
 800013e:   bd08        pop {r3, pc}
 8000140:   00000000    .word   0x00000000
 8000144:   200000b8    .word   0x200000b8
 8000148:   08008f50    .word   0x08008f50
 
0800014c <strlen>:
 800014c:   4603        mov r3, r0
 800014e:   f813 2b01   ldrb.w  r2, [r3], #1
 8000152:   2a00        cmp r2, #0
 8000154:   d1fb        bne.n   800014e <strlen+0x2>
 8000156:   1a18        subs    r0, r3, r0
 8000158:   3801        subs    r0, #1
 800015a:   4770        bx  lr
 
0800015c <__aeabi_drsub>:
 800015c:   f081 4100   eor.w   r1, r1, #2147483648 ; 0x80000000
 8000160:   e002        b.n 8000168 <__adddf3>
 8000162:   bf00        nop
 
08000164 <__aeabi_dsub>:
 8000164:   f083 4300   eor.w   r3, r3, #2147483648 ; 0x80000000
 
08000168 <__adddf3>:
 8000168:   b530        push    {r4, r5, lr}
 800016a:   ea4f 0441   mov.w   r4, r1, lsl #1
 800016e:   ea4f 0543   mov.w   r5, r3, lsl #1
 8000172:   ea94 0f05   teq r4, r5
 8000176:   bf08        it  eq
 8000178:   ea90 0f02   teqeq   r0, r2
 800017c:   bf1f        itttt   ne
 800017e:   ea54 0c00   orrsne.w    ip, r4, r0
 8000182:   ea55 0c02   orrsne.w    ip, r5, r2
 8000186:   ea7f 5c64   mvnsne.w    ip, r4, asr #21
 800018a:   ea7f 5c65   mvnsne.w    ip, r5, asr #21
 800018e:   f000 80e2   beq.w   8000356 <__adddf3+0x1ee>
 8000192:   ea4f 5454   mov.w   r4, r4, lsr #21
 8000196:   ebd4 5555   rsbs    r5, r4, r5, lsr #21
 800019a:   bfb8        it  lt
 800019c:   426d        neglt   r5, r5
 800019e:   dd0c        ble.n   80001ba <__adddf3+0x52>
 80001a0:   442c        add r4, r5
 80001a2:   ea80 0202   eor.w   r2, r0, r2
 80001a6:   ea81 0303   eor.w   r3, r1, r3
 80001aa:   ea82 0000   eor.w   r0, r2, r0
 80001ae:   ea83 0101   eor.w   r1, r3, r1
 80001b2:   ea80 0202   eor.w   r2, r0, r2
 80001b6:   ea81 0303   eor.w   r3, r1, r3
 80001ba:   2d36        cmp r5, #54 ; 0x36
 80001bc:   bf88        it  hi
 80001be:   bd30        pophi   {r4, r5, pc}
 80001c0:   f011 4f00   tst.w   r1, #2147483648 ; 0x80000000
 80001c4:   ea4f 3101   mov.w   r1, r1, lsl #12
 80001c8:   f44f 1c80   mov.w   ip, #1048576    ; 0x100000
 80001cc:   ea4c 3111   orr.w   r1, ip, r1, lsr #12
 80001d0:   d002        beq.n   80001d8 <__adddf3+0x70>
 80001d2:   4240        negs    r0, r0
 80001d4:   eb61 0141   sbc.w   r1, r1, r1, lsl #1
 80001d8:   f013 4f00   tst.w   r3, #2147483648 ; 0x80000000
 80001dc:   ea4f 3303   mov.w   r3, r3, lsl #12
 80001e0:   ea4c 3313   orr.w   r3, ip, r3, lsr #12
 80001e4:   d002        beq.n   80001ec <__adddf3+0x84>
 80001e6:   4252        negs    r2, r2
 80001e8:   eb63 0343   sbc.w   r3, r3, r3, lsl #1
 80001ec:   ea94 0f05   teq r4, r5
 80001f0:   f000 80a7   beq.w   8000342 <__adddf3+0x1da>
 80001f4:   f1a4 0401   sub.w   r4, r4, #1
 80001f8:   f1d5 0e20   rsbs    lr, r5, #32
 80001fc:   db0d        blt.n   800021a <__adddf3+0xb2>
 80001fe:   fa02 fc0e   lsl.w   ip, r2, lr
 8000202:   fa22 f205   lsr.w   r2, r2, r5
 8000206:   1880        adds    r0, r0, r2
 8000208:   f141 0100   adc.w   r1, r1, #0
 800020c:   fa03 f20e   lsl.w   r2, r3, lr
 8000210:   1880        adds    r0, r0, r2
 8000212:   fa43 f305   asr.w   r3, r3, r5
 8000216:   4159        adcs    r1, r3
 8000218:   e00e        b.n 8000238 <__adddf3+0xd0>
 800021a:   f1a5 0520   sub.w   r5, r5, #32
 800021e:   f10e 0e20   add.w   lr, lr, #32
 8000222:   2a01        cmp r2, #1
 8000224:   fa03 fc0e   lsl.w   ip, r3, lr
 8000228:   bf28        it  cs
 800022a:   f04c 0c02   orrcs.w ip, ip, #2
 800022e:   fa43 f305   asr.w   r3, r3, r5
 8000232:   18c0        adds    r0, r0, r3
 8000234:   eb51 71e3   adcs.w  r1, r1, r3, asr #31
 8000238:   f001 4500   and.w   r5, r1, #2147483648 ; 0x80000000
 800023c:   d507        bpl.n   800024e <__adddf3+0xe6>
 800023e:   f04f 0e00   mov.w   lr, #0
 
 
....
Добавлено через 7 минут
Также пробовал увеличивать кучу и стек. c 200 и 400 на 500 и 700, ничего не поменялось.
0
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
13.10.2021, 22:27 12
Найдите адрес этого BFAR и считайте значение из него самостоятельно. Может, IDE глючит.
0
Модератор
Эксперт по электронике
8490 / 6317 / 854
Регистрация: 14.02.2011
Сообщений: 21,888
13.10.2021, 22:28 13
Цитата Сообщение от OlegD_STM32 Посмотреть сообщение
но в нем я не нашел инструкции по адресу 0x22E6F0.
адреса 0x200000 и выше это ОЗУ там инструкций не может быть
0
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
13.10.2021, 22:33 14
Озу начинается с 0x20000000, там больше нулей. И код там может быть, при большом желании. Но да, это не то.
OlegD_STM32, переполнение стека отслеживается через заполнение его известным паттерном (числом) и проверкой после падения.
0
865 / 533 / 174
Регистрация: 30.07.2015
Сообщений: 1,723
13.10.2021, 23:33 15
OlegD_STM32, Вам правильно сказал Humanoid, в хардфолт уходит из I2C_WaitOnBT...(судя по скрину), достаточно найти эту функцию и поставить туда точку останова и проверять, что там творится. Объективно вьюха колл стека вам уже все показал.
0
Модератор
Эксперт по электронике
8490 / 6317 / 854
Регистрация: 14.02.2011
Сообщений: 21,888
13.10.2021, 23:49 16
Цитата Сообщение от Rius Посмотреть сообщение
Озу начинается с 0x20000000,
миль пардон, обделался нули не подсчитал
0
144 / 109 / 24
Регистрация: 15.11.2012
Сообщений: 631
14.10.2021, 00:41 17
PM0056 Programming manual (с сайта st) содержит раздел Exception Model, в котором есть Exception Entry and return.
Там нам сообщается, что при вызове исключения в стек складываются данные:
R0-R3, R12
Return address
PSR
LR

Интересен Return address. Это адрес следующей за той ассемблерной инструкцией, которая исключение вызвала.
0
5 / 5 / 0
Регистрация: 26.11.2018
Сообщений: 245
14.10.2021, 22:03  [ТС] 18
Цитата Сообщение от ValeryS Посмотреть сообщение
адреса 0x200000 и выше это ОЗУ там инструкций не может быть
Цитата Сообщение от Rius Посмотреть сообщение
переполнение стека отслеживается через заполнение его известным паттерном (числом) и проверкой после падения.
если закомментировать часть кода, который выводит имя выбранного пунккту меню, тогда падение в HardFault_Handler не происходит
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void nrf_rx_mode(void)
{
    clearn_oled();
    NRF24_init_RX_mode();
    print_rectangle_on_head();
 
    //-------------------------------------------------
    // Print selected name of menu
//  char str[16] = {0};
    //strncpy(str, currentItem -> name, 15);
//  ssd1306_SetCursor(10, 3);
//  ssd1306_WriteString(str,  Font_7x10, White);
//  ssd1306_UpdateScreen();
//  memset(str, 0, sizeof(str));
    //-------------------------------------------------
 
    button_status = BOTTON_DOESENT_PRESS;
    block_interrupt_form_up_and_down_buttons = true;
    // waiting for press enter(SW2) button
    do{
        NRF24L01_Receive();
    }while (button_status != BUTTON_ENTER);
 
    NRF24_WriteReg(CONFIG, 0x00);                                       // STOP work with nrf module  (Power off)
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);                // Turn off GREEN LED
    block_interrupt_form_up_and_down_buttons = false;
    // Return to first item of current menu
    currentItem = &items_menu_2[0];                                     // Set global pointer on first menu
    print_menu_items();                                                 // Print items on OLED
}
Добавлено через 12 минут
Если в функцию добавить этот код, или этот, то происходит HardFault_Handler
C
1
2
3
4
5
6
7
8
9
    //-------------------------------------------------
    // Print selected name of menu
//  char str[16] = {0};
    //strncpy(str, currentItem -> name, 15);
//  ssd1306_SetCursor(10, 3);
//  ssd1306_WriteString(str,  Font_7x10, White);
//  ssd1306_UpdateScreen();
//  memset(str, 0, sizeof(str));
    //-------------------------------------------------
C
1
2
3
4
5
6
7
8
9
10
11
    // Test
    int int_array[10][10]={0};
    int i,j = 0;
    for(i = 0; i < 10; i++)
    {
        for(j = 0; j < 10; j++)
        {
            int_array[i][j] = 1;
        }
        j = 0;
    }
Из этого я могу сделать вывод, что переполняется стек, потому что в оперативной мамяти инициализируется слишком много переменных.
Правильно я думаю? как определить который должен быть стек и куча, для программы? сейчас куча = 0х500, стек = 0х700
0
Эксперт .NET
7586 / 5069 / 1209
Регистрация: 25.05.2015
Сообщений: 15,463
Записей в блоге: 14
14.10.2021, 22:13 19
C++
1
int int_array[10][10]={0};
= 400 байт. Жирно.

как определить который должен быть стек и куча, для программы
Делаем по максимуму, во всю оперативу. Забиваем всё это паттерном. Запускаем, гоняем. Смотрим, сколько паттернов затёрлось.
0
Модератор
Эксперт по электронике
8490 / 6317 / 854
Регистрация: 14.02.2011
Сообщений: 21,888
14.10.2021, 23:21 20
Цитата Сообщение от OlegD_STM32 Посмотреть сообщение
Из этого я могу сделать вывод, что переполняется стек, потому что в оперативной мамяти инициализируется слишком много переменных.
сделай их глобальными или объяви static тогда они не будут занимать стек
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.10.2021, 23:21

Разработать функцию, при выполнении которой происходит построение конуса второго порядка
2.Разработать функцию, при выполнении которой происходит построение конуса второго порядка. Функция...

При отключение и включении питания,происходит сбой видеокарты на 7?Как исправить?
При отключение и включении питания,происходит сбой видеокарты на 7?Как исправить?

Пишу инструкцию. Кто подскажет почему выбираю путь только один раз , остальную инструкцию программа выполняет сама. Как
#include&lt;iostream&gt; using namespace std; int main() { int Right, Left, Up, Low; bool...

Как узнать, какой из пакетов обновления дает сбой?
После обновления BSOD ошибка c0000145 application error. Все пишут что KB3045999 - обновление...

Добавление метабокса (происходит сбой)
Всем привет! Подскажите, пожалуйста, как добавить второй метабокс? Один уже есть и при попытке...

После do-while происходит сбой программы
Ввёл код, что был на уроке #include &lt;stdio.h&gt; #include &lt;conio.h&gt; int main() { int a, sum...

Массивы. Написать инструкцию, по которой меняется 1 и последний элемент массива
Дан массив int arr={4,6,1,2,4,5,9,3}. Написать инструкцию, по которой меняется 1 и последний...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.