Перейти к содержанию
    

опять про оптимизацию :( глюк нашел вроде

во время выполнения 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 не влияет на исполнение. Поскольку я в ассемблере мягко говоря не силен, одолеть эту задачку мне оказалось не по зубам

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку я в ассемблере мягко говоря не силен, одолеть эту задачку мне оказалось не по зубам

Не заметили волшебное превращение ARM в Thumb:

00017E74 E2811001 ADD R1, R1, #0x1

00017E78 6001 STR R1, [R0, #0]

Так в жизни не бывает :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не заметили волшебное превращение ARM в Thumb:

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

 

Так в жизни не бывает :(

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жестко... А посмотрите в листинг, где еще встречается ?Subroutine0, т.е. кто к ней ходит?

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Жестко... А посмотрите в листинг, где еще встречается ?Subroutine0, т.е. кто к ней ходит?

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

 

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

IAR ARM 5.30.1, LPC 2478, оптимизация максимальная(hz), все параметры вызова компилятора есть в листинге

listing.rar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...

 

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

 

1. Не использовать в одном файле одновременно __arm и __thumb

2. Забить на тумбу в принципе, хотя бы в операционке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...

 

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

 

1. Не использовать в одном файле одновременно __arm и __thumb

2. Забить на тумбу в принципе, хотя бы в операционке.

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

IAR 5.20, кстати, ведет себя аналогично, а вот в 4.41 подобных глюков не было (правда, там процессор STR710)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

пока что влепил #pragma optimize = medium для этих двух функций, полет нормальный.

 

Поставили бы Вы оптимизацию High Speed, а не Size.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поставили бы Вы оптимизацию High Speed, а не Size.

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

Впрочем, надо будет попробовать все равно

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

проект здоровый, в самом большом варианте еле-еле помещается в ПЗУ контроллера

 

Возьмите следующий камень в линейке. Тем более, что цены на LPC более чем демократичны. Или 2478 - самый здоровый по Flash? Если да, то предлагаю такой способ. Указываете High Speed и руками для каждого файла выбираете ARM или Thumb. Причем, операционку очень желательно в ARM-режиме собирать, веселее будет. А дальше смотреть по месту.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возьмите следующий камень в линейке. Тем более, что цены на LPC более чем демократичны. Или 2478 - самый здоровый по Flash? Если да, то предлагаю такой способ. Указываете High Speed и руками для каждого файла выбираете ARM или Thumb. Причем, операционку очень желательно в ARM-режиме собирать, веселее будет. А дальше смотреть по месту.

сами понимаете, просто так "взять следующий камень" не так просто, как хотелось бы, при серийном производстве. впрочем, 2478 тьфу-тьфу пока по этим параметрам не напрягает, речь была про STR710, а он-таки самый жирный в линейке.

насчет предложенного способа - спасибо, попробую, как только образуется дыра в расписании. щас вот бьюсь, в другом месте вылезли глюки в многократно отлаженном на разных процессорах коде :( уже подумываю откатиться на 4.41 :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

сами понимаете, просто так "взять следующий камень" не так просто, как хотелось бы, при серийном производстве. впрочем, 2478 тьфу-тьфу пока по этим параметрам не напрягает, речь была про STR710, а он-таки самый жирный в линейке.

насчет предложенного способа - спасибо, попробую, как только образуется дыра в расписании. щас вот бьюсь, в другом месте вылезли глюки в многократно отлаженном на разных процессорах коде :( уже подумываю откатиться на 4.41 :(

попробовал собрать проект с оптимизацией по скорости. размер вырос со 130К до 170К, глюки с data_abort в отлаженном коде пропали. Пока работаю так, дальше посмотрим

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

очередной глюк с data abort в отлаженном коде, при вызове виртуального метода. на этот раз с оптимизацией по скорости. полдня убил, лечится, как обычно, снижением уровня оптимизации в конкретной функции. Чувствую, откачусь я на 4.41, мне такие сюрпризы все нервы съедят :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

очередной глюк с data abort в отлаженном коде, при вызове виртуального метода. на этот раз с оптимизацией по скорости. полдня убил, лечится, как обычно, снижением уровня оптимизации в конкретной функции. Чувствую, откачусь я на 4.41, мне такие сюрпризы все нервы съедят :(

А вы не пробовали урезать проект до минимума, но так, чтобы баг проявлялся, и в багрепорт IAR отписать?

Все же при баг-репорте на лицензионность ПО пофиг, тем более вы можете сослаться на то, что работаете с eval версией.

Я так отписывал им еще на 4.20, в следующей версии посмотрел на список изменений, мой баг фигурировал как исправленный.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрел. А что, у нас нынче IAR сам выбирает, какой ему режим делать? Что-то я вижу в листинге помесь arm и thumb, но не вижу ни __arm, ни __thumb...

 

Это как раз просто - инструкции MRS и MSR существуют только для arm режима, поэтому при вызове функций разрешения и запрещения прерываний принудительно устанавливается режим arm.

Судя по всему, функции __disable_interrupt() и __enable_interrupt() инлайнятся, и компилятор ту функцию, из которой они вызываются также переводит режим ARM. Возможно, у него есть какие-то критерии, когда он это будет делать. Предположу, что если размер функции относительно небольшой, то он будет выполнять такую оптимизацию, а если большой - то нет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...