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

 
 
 
Reply to this topicStart new topic
> volatile, тонкости
Jat
сообщение Dec 16 2010, 03:51
Сообщение #1





Группа: Участник
Сообщений: 8
Регистрация: 6-03-06
Из: Новосибирск
Пользователь №: 15 027



Вот примерчик ошибки в генерации кода для cortex

код такой

volatile int *p;
void proc(void) { *p = 1; }

здесь чтения переменной быть *p быть не должно!
только запись!
а генерится и чтение тоже

CODE

proc:
movw r3, #:lower16:p
movt r3, #:upper16:p
ldr r3, [r3, #0] !!!!!!!!!!!!!!!!! Во это совсем не надо!
mov r2, #1
str r2, [r3, #0]
bx lr
.size proc, .-proc
.comm p,4,4
.ident "GCC: (Klen's GCC package (KGP) for ARM/elf platform) 4.6.0 20101212 (experimental)"





Сообщение отредактировал Jat - Dec 16 2010, 03:57
Go to the top of the page
 
+Quote Post
adnega
сообщение Dec 16 2010, 04:07
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



вроде все ок.
сначала в r3 заносится адрес слова в памяти программ, где лежит адрес на p.
затем этот адрес извлекается и по нему производится запись.
Go to the top of the page
 
+Quote Post
Jat
сообщение Dec 16 2010, 04:22
Сообщение #3





Группа: Участник
Сообщений: 8
Регистрация: 6-03-06
Из: Новосибирск
Пользователь №: 15 027



Да, прошу прощения, это я попутался!
Сомнения у меня возникли вот из этого куска листинга

CODE
226:Lib/StdPeriph/src/stm32f10x_rcc.c **** void RCC_DeInit(void)
227:Lib/StdPeriph/src/stm32f10x_rcc.c **** {
26 .loc 1 227 0
27 .cfi_startproc
28 @ args = 0, pretend = 0, frame = 0
29 @ frame_needed = 0, uses_anonymous_args = 0
30 @ link register save eliminated.
228:Lib/StdPeriph/src/stm32f10x_rcc.c **** /* Set HSION bit */
229:Lib/StdPeriph/src/stm32f10x_rcc.c **** RCC->CR |= (uint32_t)0x00000001;
31 .loc 1 229 0
32 0000 104B ldr r3, .L2
33 0002 1A68 ldr r2, [r3, #0]
34 0004 1968 ldr r1, [r3, #0]
35 0006 42F00102 orr r2, r2, #1
36 000a 1A60 str r2, [r3, #0]
230:Lib/StdPeriph/src/stm32f10x_rcc.c ****
231:Lib/StdPeriph/src/stm32f10x_rcc.c **** /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
232:Lib/StdPeriph/src/stm32f10x_rcc.c **** #ifndef STM32F10X_CL
233:Lib/StdPeriph/src/stm32f10x_rcc.c **** RCC->CFGR &= (uint32_t)0xF8FF0000;
37 .loc 1 233 0
38 000c 5968 ldr r1, [r3, #4]
39 000e 0E4A ldr r2, .L2+4
40 0010 0A40 ands r2, r2, r1
41 0012 5968 ldr r1, [r3, #4]
42 0014 5A60 str r2, [r3, #4]


Сообщение отредактировал Jat - Dec 16 2010, 06:21
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 16 2010, 06:52
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Ну так а тут идёт операция чтение-модификация-запись, что запрошено, то и делается.
Цитата
var op= expression;
это то же самое, что и
Цитата
var = var op (expression);
Т.е. чтение var тут как ни крути, а есть.
Ну, если строго, то за исключением того, что адрес объекта var, в данном случае RCC->CR, вычисляется один раз (тонкость проявляется в случае, если лично сам указатель volatile, например, int * volatile p;, а как квалифицировано то, на что он указывает - не важно).
Впрочем, это вопрос не по этой теме, а где-то в разъяснениях тонкостей языков С/С++.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 16 2010, 07:02
Сообщение #5


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Jat @ Dec 16 2010, 12:22) *
Да, прошу прощения, это я попутался!
Сомнения у меня возникли вот из этого куска листинга

А почему в листинге двойное чтение памяти/периферии?
Смысла я не понимаю.

Цитата(ReAl @ Dec 16 2010, 14:52) *
Т.е. чтение var тут как ни крути, а есть.

Чтение одинарное есть. А двойное для волатила это как бы перебор. Можно и на грабли нарваться.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Dec 16 2010, 07:31
Сообщение #6


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Jat, я вынес Ваш вопрос из другой темы. Не следует с частными вопросами вклиниваться в чужую тему.
Модератор
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 16 2010, 09:02
Сообщение #7


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(GetSmart @ Dec 16 2010, 12:02) *
Чтение одинарное есть. А двойное для волатила это как бы перебор. Можно и на грабли нарваться.
Ой, точно. Увлёкся вопросом "а почему чтение" и не заметил, что их по два.
Странно.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Dec 16 2010, 09:57
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Цитата(Jat @ Dec 16 2010, 10:51) *
Вот примерчик ошибки в генерации кода для cortex

код такой

volatile int *p;
void proc(void) { *p = 1; }

здесь чтения переменной быть *p быть не должно!
только запись!
а генерится и чтение тоже

CODE

proc:
movw r3, #:lower16:p
movt r3, #:upper16:p
ldr r3, [r3, #0] !!!!!!!!!!!!!!!!! Во это совсем не надо!
mov r2, #1
str r2, [r3, #0]
bx lr
.size proc, .-proc
.comm p,4,4
.ident "GCC: (Klen's GCC package (KGP) for ARM/elf platform) 4.6.0 20101212 (experimental)"


Нет тут никакой ошибки. Вы же хотите чо-то записать по адресу, на который указывает p (кстати, у вас он указывает на неопределенную память!). Таким образом:
- первое чтение - получаем сам указатель (p),
- второе чтение - получаем адрес, на который указывает p,
- записываем то, что хотим по этому адресу.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 16 2010, 12:10
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Jat @ Dec 16 2010, 09:22) *
Сомнения у меня возникли вот из этого куска листинга
У меня компилируется нормально. Но у меня давненько уже выложенная Klen-ом линуксовая версия
Цитата
arm-kgp-eabi-gcc (Klen's GCC package (KGP) for ARM/elf platform) 4.6.0 20100525 (experimental)

CODE
6:main.c **** void RCC_DeInit()
7:main.c **** {
31 .loc 1 7 0
32 .cfi_startproc
33 @ args = 0, pretend = 0, frame = 0
34 @ frame_needed = 0, uses_anonymous_args = 0
35 @ link register save eliminated.
8:main.c **** RCC->CR |= (uint32_t)0x00000001;
36 .loc 1 8 0
37 0000 054B ldr r3, .L2
38 0002 1A68 ldr r2, [r3, #0]
39 0004 42F00102 orr r2, r2, #1
40 0008 1A60 str r2, [r3, #0]
9:main.c **** #ifndef STM32F10X_CL
10:main.c **** RCC->CFGR &= (uint32_t)0xF8FF0000;
41 .loc 1 10 0
42 000a 5968 ldr r1, [r3, #4]
43 000c 034A ldr r2, .L2+4
44 000e 01EA0202 and r2, r1, r2
45 0012 5A60 str r2, [r3, #4]
11:main.c **** #endif
12:main.c **** }
46 .loc 1 12 0
47 0014 7047 bx lr
48 .L3:
49 0016 00BF .align 2
50 .L2:
51 0018 00100240 .word 1073876992
52 001c 0000FFF8 .word -117506048
А в Вашем листинге таки читается по два раза, причём использутся первое чтение, а результат ворого отбрасывается.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Jat
сообщение Dec 18 2010, 08:05
Сообщение #10





Группа: Участник
Сообщений: 8
Регистрация: 6-03-06
Из: Новосибирск
Пользователь №: 15 027



Цитата(GetSmart @ Dec 16 2010, 16:02) *
А почему в листинге двойное чтение памяти/периферии?
Смысла я не понимаю.


А его и нет... laughing.gif
Это ошибка кодогенерации...

Цитата(GetSmart @ Dec 16 2010, 16:02) *
Чтение одинарное есть. А двойное для волатила это как бы перебор. Можно и на грабли нарваться.


Именно... нарвался... crying.gif

Разобрался как это обойти.
Такой эффект вызывает ключ -fpack-struct
Без него все генерится нормально. Никаких лишних чтений.

Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 18 2010, 08:14
Сообщение #11


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Jat @ Dec 18 2010, 15:05) *
Такой эффект вызывает ключ -fpack-struct
Без него все генерится нормально. Никаких лишних чтений.

Цитата(ГЦЦ4.5.1)
Warning: the -fpack-struct switch causes GCC to generate code that is not binary compatible with code generated without that switch. Additionally, it makes the code suboptimal. Use it to conform to a non-default application binary interface.

То ли бага, то ли фича... smile3046.gif
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Dec 18 2010, 08:21
Сообщение #12


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(Jat @ Dec 18 2010, 16:05) *
Это ошибка кодогенерации...

Я конечно так и понял. Не понял зачем оно так "ошибается".


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 25th July 2025 - 13:55
Рейтинг@Mail.ru


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