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

 
 
> Компиляция 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



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

 


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


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