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

 
 
> Компиляция ARM GCC, куда пропадают циклы while?
venomsoldier
сообщение Aug 22 2013, 09:13
Сообщение #1





Группа: Участник
Сообщений: 12
Регистрация: 26-02-07
Пользователь №: 25 677



Начал изучать арм, написал функцию:

Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    *((uint32_t *)(0x2000B8A0))=val+channel;
}

Функция читает регистр статуса по адресу 0x2000B898 и ждет нолика в старшем бите, после этого записывает в 0x2000B8A0 значения.

Компилятор версии ARM/GNU C Compiler 4.7.3, шел в комплекте с Atmel Studio 6.1 (папка с именем 4.7.3.1029)

Опции компилятора использую следующие:
Код
-marm -DBCM2835 -DDEBUG  -O0 -ffunction-sections -mlong-calls -g2 -Wall -mcpu=arm1176jzf-s -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)"

Опции линкера:
Код
-marm -nostartfiles -nodefaultlibs -nostdlib -Wl,-Map="$(OutputFileName).map" -Wl,--start-group -lm  -Wl,--end-group -L"../cmsis/linkerScripts"  -Wl,--gc-sections -mcpu=arm1176jzf-s


Компилирую с оптимизацией 0 (-O0), получаю листинг:
Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    8028:    e52db004     push    {fp}; (str fp, [sp, #-4]!)
    802c:    e28db000     add    fp, sp, #0
    8030:    e24dd00c     sub    sp, sp, #12
    8034:    e50b0008     str    r0, [fp, #-8]
    8038:    e1a03001     mov    r3, r1
    803c:    e54b3009     strb    r3, [fp, #-9]
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    8040:    e1a00000     nop; (mov r0, r0)
    8044:    e59f3028     ldr    r3, [pc, #40]; 8074 <MailboxWrite+0x4c>
    8048:    e5933000     ldr    r3, [r3]
    804c:    e3530000     cmp    r3, #0
    8050:    bafffffb     blt    8044 <MailboxWrite+0x1c>
    *((uint32_t *)(0x2000B8A0))=val+channel;
    8054:    e59f301c     ldr    r3, [pc, #28]; 8078 <MailboxWrite+0x50>
    8058:    e55b1009     ldrb    r1, [fp, #-9]
    805c:    e51b2008     ldr    r2, [fp, #-8]
    8060:    e0812002     add    r2, r1, r2
    8064:    e5832000     str    r2, [r3]
}
    8068:    e28bd000     add    sp, fp, #0
    806c:    e8bd0800     pop    {fp}
    8070:    e12fff1e     bx    lr
    8074:    2000b898     .word    0x2000b898
    8078:    2000b8a0     .word    0x2000b8a0

Вроде всё работает по плану, только какие-то ненужные манипуляции с sp и fp, вобщем, много лишнего.

Компилирую с оптимизацией 1 (-O1), получаю листинг:
Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    8020:    e59f301c     ldr    r3, [pc, #28]; 8044 <MailboxWrite+0x24>
    8024:    e5933898     ldr    r3, [r3, #2200]; 0x898
    8028:    e3530000     cmp    r3, #0
    802c:    ba000003     blt    8040 <MailboxWrite+0x20>
    *((uint32_t *)(0x2000B8A0))=val+channel;
    8030:    e0810000     add    r0, r1, r0
    8034:    e59f3008     ldr    r3, [pc, #8]; 8044 <MailboxWrite+0x24>
    8038:    e58308a0     str    r0, [r3, #2208]; 0x8a0
    803c:    e12fff1e     bx    lr
    8040:    eafffffe     b    8040 <MailboxWrite+0x20>
    8044:    2000b000     .word    0x2000b000

Вот тут лишних манипуляций не происходит, но пропадает цикл while, один раз проверяется статусный бит (802с) и проц уходит в бесконечный цикл (8040).

Компилирую с оптимизацией 2 (-O2), получаю листинг:
Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    8020:    e59f3018     ldr    r3, [pc, #24]; 8040 <MailboxWrite+0x20>
    8024:    e5932898     ldr    r2, [r3, #2200]; 0x898
    8028:    e3520000     cmp    r2, #0
    802c:    ba000002     blt    803c <MailboxWrite+0x1c>
    *((uint32_t *)(0x2000B8A0))=val+channel;
    8030:    e0810000     add    r0, r1, r0
    8034:    e58308a0     str    r0, [r3, #2208]; 0x8a0
    8038:    e12fff1e     bx    lr
    803c:    eafffffe     b    803c <MailboxWrite+0x1c>
    8040:    2000b000     .word    0x2000b000

Тут тоже самое, что и О1, но не происходит перезагрузки регистра с адресом, цикл while так же отсутствует.

Компилирую с оптимизацией 3 (-O3), получаю листинг:
Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    8020:    e59f3018     ldr    r3, [pc, #24]; 8040 <MailboxWrite+0x20>
    8024:    e5932898     ldr    r2, [r3, #2200]; 0x898
    8028:    e3520000     cmp    r2, #0
    802c:    aa000000     bge    8034 <MailboxWrite+0x14>
    8030:    eafffffe     b    8030 <MailboxWrite+0x10>
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    *((uint32_t *)(0x2000B8A0))=val+channel;
    8034:    e0810000     add    r0, r1, r0
    8038:    e58308a0     str    r0, [r3, #2208]; 0x8a0
    803c:    e12fff1e     bx    lr
    8040:    2000b000     .word    0x2000b000

Тут уже сразу зацикливается никуда не перепрыгивая (8030)

Компиляция с оптимизацией s (-Os), приводит к результату -O2.

Еще есть опция -Ofast
Код
void MailboxWrite(uint32_t val, uint8_t channel)
{
    8020:    e59f3018     ldr    r3, [pc, #24]; 8040 <MailboxWrite+0x20>
    8024:    e5932898     ldr    r2, [r3, #2200]; 0x898
    8028:    e3520000     cmp    r2, #0
    802c:    aa000000     bge    8034 <MailboxWrite+0x14>
    8030:    eafffffe     b    8030 <MailboxWrite+0x10>
    while(*((uint32_t *)(0x2000B898))&0x80000000);
    *((uint32_t *)(0x2000B8A0))=val+channel;
    8034:    e0810000     add    r0, r1, r0
    8038:    e58308a0     str    r0, [r3, #2208]; 0x8a0
    803c:    e12fff1e     bx    lr
    8040:    2000b000     .word    0x2000b000


Подскажите, как можно ришить мою проблему? Может еще какие опции добавить компилятору? Может я неверно пишу программу??? ))



Сообщение отредактировал venomsoldier - Aug 22 2013, 09:15
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
venomsoldier
сообщение Aug 22 2013, 11:49
Сообщение #2





Группа: Участник
Сообщений: 12
Регистрация: 26-02-07
Пользователь №: 25 677



Спасибо огромное.
Пока ходил погулять, до меня дошло, перед адресом нужно указать, что это относится к периферии.

Для АВРов было что-то вроде _SFR_IO8(0x26) и _SFR_MEM8(0x60).

Завтра попробую откомпилить указанный вами код. Еще раз спасибо.

Сообщение отредактировал venomsoldier - Aug 22 2013, 11:54
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 22 2013, 13:05
Сообщение #3


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(venomsoldier @ Aug 22 2013, 14:49) *
Спасибо огромное.
Пока ходил погулять, до меня дошло, перед адресом нужно указать, что это относится к периферии.

Для АВРов было что-то вроде _SFR_IO8(0x26) и _SFR_MEM8(0x60).

А готовых описаний нету чтоли? Что за контроллер такой?


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Aug 22 2013, 13:16
Сообщение #4


Гуру
******

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



Цитата(MrYuran @ Aug 22 2013, 16:05) *
Что за контроллер такой?

Raspberry Pi наверное...

Цитата(venomsoldier @ Aug 22 2013, 14:49) *
Для АВРов было что-то вроде _SFR_IO8(0x26) и _SFR_MEM8(0x60).

Что наверное соответствует

Код
__no_init volatile unsigned char
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 19th June 2025 - 06:21
Рейтинг@Mail.ru


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