Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: опять про оптимизацию :( глюк нашел вроде
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
sergik_vrn
во время выполнения FreeRTOS непонятным образом сами собой запрещались прерывания. Путем несложной трассировки выяснил, что происходят они при парном вызове vPortEnterCritical() - vPortExitCritical(), по принципу
Код
portTickType xTaskGetTickCount( void )
{
portTickType xTicks;

    /* Critical section required if running on a 16 bit processor. */
    taskENTER_CRITICAL();
    {
        xTicks = xTickCount;
    }
    taskEXIT_CRITICAL();

    return xTicks;
}

сами процедуры с виду простейшие
Код
void vPortEnterCritical( void )
{
    /* Disable interrupts first! */
    __disable_interrupt();

    /* Now interrupts are disabled ulCriticalNesting can be accessed
    directly.  Increment ulCriticalNesting to keep a count of how many times
    portENTER_CRITICAL() has been called. */
    ulCriticalNesting++;
}
/*-----------------------------------------------------------*/
void vPortExitCritical( void )
{
    if( ulCriticalNesting > portNO_CRITICAL_NESTING )
    {
        /* Decrement the nesting count as we are leaving a critical section. */
        ulCriticalNesting--;

        /* If the nesting level has reached zero then interrupts should be
        re-enabled. */
        if( ulCriticalNesting == portNO_CRITICAL_NESTING )
        {
            __enable_interrupt();
        }
    }
}

portNO_CRITICAL_NESTING разумеется = 0


однако, что я получаю при трасировке:
Код
??vPortPreemptiveTick_0:
  00017E5C  004000E0  DC32         0xE0004000
__disable_interrupt();
vPortEnterCritical:
vPortEnterCritical:
  00017E60  E10F0000  MRS          R0, CPSR
  00017E64  E38000C0  ORR          R0, R0, #0xC0
  00017E68  E121F000  MSR          CPSR_c, R0
ulCriticalNesting++;
  00017E6C  E59F003C  LDR          R0, [PC, #+60]          ; [??DataTable1 (0x17EB0)] =ulCriticalNesting (0x4000F3B8)
  00017E70  E5901000  LDR          R1, [R0, #+0]
  00017E74  E2811001  ADD          R1, R1, #0x1

до этого момента все выполняется как надо, адрес в R0, правильное значение в R1

*pxTopOfStack = portNO_CRITICAL_NESTING;
Next label is a Thumb label
?Subroutine0:
.text_19:
  00017E78  6001      STR          R1, [R0, #0]

не имеет никакого эффекта, значение не обновляется

return pxTopOfStack;
  00017E7A  4770      BX           LR

не выполняется вообще
соттветственно, дальше выполняется vPortExitCritical:

if( ulCriticalNesting > portNO_CRITICAL_NESTING )
vPortExitCritical:
vPortExitCritical:
  00017E7C  E59F002C  LDR          R0, [PC, #+44]          ; [??DataTable1 (0x17EB0)] =ulCriticalNesting (0x4000F3B8)
  00017E80  E5901000  LDR          R1, [R0, #+0]
  00017E84  E3510000  CMP          R1, #0x0

поскольку значение ulCriticalNesting не было инкрементировано, проверка отрицательная, дальше выход

  00017E88  0A000007  BEQ          ??vPortExitCritical_0   ; 0x17EAC


  ulCriticalNesting--;
  00017E8C  E5901000  LDR          R1, [R0, #+0]
  00017E90  E2411001  SUB          R1, R1, #0x1
  00017E94  E5801000  STR          R1, [R0, #+0]
  if( ulCriticalNesting == portNO_CRITICAL_NESTING )
  00017E98  E5900000  LDR          R0, [R0, #+0]
  00017E9C  E3500000  CMP          R0, #0x0
   __enable_interrupt();
  00017EA0  010F0000  MRSEQ        R0, CPSR
  00017EA4  03C000C0  BICEQ        R0, R0, #0xC0
  00017EA8  0121F000  MSREQ        CPSR_c, R0
}
??vPortExitCritical_0:
  00017EAC  E12FFF1E  BX           LR

...


итог - после выхода из vPortEnterCritical значение ulCriticalNesting нулевое, прерывания запрещены, вызов vPortExitCritical не имеет значения. При уменьшении уровня оптимизации все нормализуется. volatile не влияет на исполнение. Поскольку я в ассемблере мягко говоря не силен, одолеть эту задачку мне оказалось не по зубам
aaarrr
Цитата(sergik_vrn @ Feb 4 2009, 14:52) *
Поскольку я в ассемблере мягко говоря не силен, одолеть эту задачку мне оказалось не по зубам

Не заметили волшебное превращение ARM в Thumb:
Цитата
00017E74 E2811001 ADD R1, R1, #0x1
00017E78 6001 STR R1, [R0, #0]

Так в жизни не бывает sad.gif
sergik_vrn
Цитата(aaarrr @ Feb 4 2009, 14:56) *
Не заметили волшебное превращение ARM в Thumb:

ну я вообще-то задумался, откуда там thumb, но понимания от этого не прибавилось smile.gif кстати, если процедуру сделать __arm (кстати, в порте под STR710 она именно __arm __interwork), результат не меняется, буква в букву

Цитата
Так в жизни не бывает sad.gif

однако, это компилятор такой код генеряет. и, судя по всему, мешает thumb c arm в целях оптимизации (во всяком случае, вызов *pxTopOfStack = portNO_CRITICAL_NESTING; явно не отсюда приплетен. ошибка?
Rst7
Жестко... А посмотрите в листинг, где еще встречается ?Subroutine0, т.е. кто к ней ходит?

И кстати, что за компилятор? Версия, в смысле, ну и прочие параметры настроек.
sergik_vrn
Цитата(Rst7 @ Feb 4 2009, 15:57) *
Жестко... А посмотрите в листинг, где еще встречается ?Subroutine0, т.е. кто к ней ходит?

прикрепил листинг-файл

Цитата
И кстати, что за компилятор? Версия, в смысле, ну и прочие параметры настроек.

IAR ARM 5.30.1, LPC 2478, оптимизация максимальная(hz), все параметры вызова компилятора есть в листинге
Rst7
Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...

Но похоже, действительно баг. Рекомендую как пути обхода:

1. Не использовать в одном файле одновременно __arm и __thumb
2. Забить на тумбу в принципе, хотя бы в операционке.
sergik_vrn
Цитата(Rst7 @ Feb 4 2009, 16:37) *
Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...

Но похоже, действительно баг. Рекомендую как пути обхода:

1. Не использовать в одном файле одновременно __arm и __thumb
2. Забить на тумбу в принципе, хотя бы в операционке.

ну, собственно, если IAR сам будет выбирать режим, то вариант 1 будет трудно реализовать на практике... пока что влепил #pragma optimize = medium для этих двух функций, полет нормальный.
IAR 5.20, кстати, ведет себя аналогично, а вот в 4.41 подобных глюков не было (правда, там процессор STR710)
Rst7
Цитата
пока что влепил #pragma optimize = medium для этих двух функций, полет нормальный.


Поставили бы Вы оптимизацию High Speed, а не Size.
sergik_vrn
Цитата(Rst7 @ Feb 4 2009, 18:33) *
Поставили бы Вы оптимизацию High Speed, а не Size.

попробую при случае. причина такого выбора метода оптимизации проста, проект здоровый, в самом большом варианте еле-еле помещается в ПЗУ контроллера. А разная компиляция - разные глюки sad.gif
Впрочем, надо будет попробовать все равно
Rst7
Цитата
проект здоровый, в самом большом варианте еле-еле помещается в ПЗУ контроллера


Возьмите следующий камень в линейке. Тем более, что цены на LPC более чем демократичны. Или 2478 - самый здоровый по Flash? Если да, то предлагаю такой способ. Указываете High Speed и руками для каждого файла выбираете ARM или Thumb. Причем, операционку очень желательно в ARM-режиме собирать, веселее будет. А дальше смотреть по месту.
sergik_vrn
Цитата(Rst7 @ Feb 4 2009, 18:58) *
Возьмите следующий камень в линейке. Тем более, что цены на LPC более чем демократичны. Или 2478 - самый здоровый по Flash? Если да, то предлагаю такой способ. Указываете High Speed и руками для каждого файла выбираете ARM или Thumb. Причем, операционку очень желательно в ARM-режиме собирать, веселее будет. А дальше смотреть по месту.

сами понимаете, просто так "взять следующий камень" не так просто, как хотелось бы, при серийном производстве. впрочем, 2478 тьфу-тьфу пока по этим параметрам не напрягает, речь была про STR710, а он-таки самый жирный в линейке.
насчет предложенного способа - спасибо, попробую, как только образуется дыра в расписании. щас вот бьюсь, в другом месте вылезли глюки в многократно отлаженном на разных процессорах коде sad.gif уже подумываю откатиться на 4.41 sad.gif
sergik_vrn
Цитата(sergik_vrn @ Feb 5 2009, 11:02) *
сами понимаете, просто так "взять следующий камень" не так просто, как хотелось бы, при серийном производстве. впрочем, 2478 тьфу-тьфу пока по этим параметрам не напрягает, речь была про STR710, а он-таки самый жирный в линейке.
насчет предложенного способа - спасибо, попробую, как только образуется дыра в расписании. щас вот бьюсь, в другом месте вылезли глюки в многократно отлаженном на разных процессорах коде sad.gif уже подумываю откатиться на 4.41 sad.gif

попробовал собрать проект с оптимизацией по скорости. размер вырос со 130К до 170К, глюки с data_abort в отлаженном коде пропали. Пока работаю так, дальше посмотрим
sergik_vrn
очередной глюк с data abort в отлаженном коде, при вызове виртуального метода. на этот раз с оптимизацией по скорости. полдня убил, лечится, как обычно, снижением уровня оптимизации в конкретной функции. Чувствую, откачусь я на 4.41, мне такие сюрпризы все нервы съедят sad.gif
Andy Mozzhevilov
Цитата(sergik_vrn @ Feb 12 2009, 17:40) *
очередной глюк с data abort в отлаженном коде, при вызове виртуального метода. на этот раз с оптимизацией по скорости. полдня убил, лечится, как обычно, снижением уровня оптимизации в конкретной функции. Чувствую, откачусь я на 4.41, мне такие сюрпризы все нервы съедят sad.gif

А вы не пробовали урезать проект до минимума, но так, чтобы баг проявлялся, и в багрепорт IAR отписать?
Все же при баг-репорте на лицензионность ПО пофиг, тем более вы можете сослаться на то, что работаете с eval версией.
Я так отписывал им еще на 4.20, в следующей версии посмотрел на список изменений, мой баг фигурировал как исправленный.
Andy Mozzhevilov
Цитата(Rst7 @ Feb 4 2009, 19:37) *
Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...


Это как раз просто - инструкции MRS и MSR существуют только для arm режима, поэтому при вызове функций разрешения и запрещения прерываний принудительно устанавливается режим arm.
Судя по всему, функции __disable_interrupt() и __enable_interrupt() инлайнятся, и компилятор ту функцию, из которой они вызываются также переводит режим ARM. Возможно, у него есть какие-то критерии, когда он это будет делать. Предположу, что если размер функции относительно небольшой, то он будет выполнять такую оптимизацию, а если большой - то нет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.