Jump to content

    

Nixon

Админы
  • Content Count

    2832
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Nixon

  • Rank
    Гуру
  • Birthday 04/29/1974

Контакты

  • Сайт
    http://

Информация

  • Город
    Киев

Recent Profile Visitors

21228 profile views
  1. Большинство недостатков препроцессора С++ ( не С, к сожалению только С++ и 11+ версий) нивелируются constexpr выражениями и шаблонами. Если у вас есть возможность использовать такие компиляторы то попробуйте, не пожалеете.
  2. Я постараюсь или убрать или как то сократить данный список
  3. Edit -> Find дальше выбираете тип объекта и или выбираете или подсвечиваете
  4. Не поможет. Точнее поможет только в примитивных случаях.
  5. А я приведу. Несколько абстрактный пример, но sapienti sat struct FOO { int A; int B; }; struct BAR { const FOO* foo; const int sum; }; constexpr int sum (const FOO foo) { return foo.A + foo.B; } constexpr FOO foo1 {1,2}; constexpr FOO foo2 {2,4}; const BAR bar1 {&foo1, sum(foo1)}; const BAR bar2 {&foo2, sum(foo2)}; void main ( void ) { int X = bar1.sum + bar2.sum; while(1); } Чтоб было понятнее - скриншотик Или вы будет утверждать что никогда не возникало потребности выполнить кучу действий на этапе компиляции? P.S. Я кстати современный С++ и рассматриваю только в плане улучшения "препроцессинга".
  6. template <typename T, int aLDA> class MDA2 { enum : int { LDA = aLDA }; public: T *A; MDA2(T *aA) : { A=aA; }; T &operator()(int i1, int i2) { return A[i2+LDA*i1]; }; T *operator()(int i1) { return A+LDA*i1; }; }; Если вы конечно не используете экземпляр класса повторно с переинициализацией LDA Чой то я, там enum вообще не нужен - используйте параметр шаблона напрямую
  7. Да, вы правы. Универсальное решение в таком случае - дамп с последующим анализом. Жаль, хотелось бы немножко автоматизировать сей процесс
  8. Меня скорее всего спасает то, что функции имеющие assert довольно тяжелые, и потому они имеют только вариант завершения с POP. P.S. Особенность проблемы в том, что ошибка возникает ОЧЕНЬ редко, на объекте и оперативно просмотреть дамп нет возможности. Коррекция самой ошибки производится сбросом с последующим восстановлением переменных всех машин состояний. В принципе как бы и решена проблема. Но хотелось бы разобраться в чем ее истоки. Проект довольно большой, многоуровневый (писали его с полдесятка человек) и потому дамп нужно хранить очень большой, а места очень мало. Вот и хотелось обойтись только стеком вызовов.
  9. Да, спасибо, нашел такое. Добавил еще поиск такого способа выхода
  10. Была такая функция подсчета битов, я ее тупо скопипастил. А какая разница что считать - сохраненные регистры или восстановленные? Разве что искать вверх придется только команды коррекции стека и PUSH. Но их тоже может не быть. Я честно говоря надеялся, что существует что-то стандартное для раскрутки стека вызовов.
  11. Сохранить верхушку стека недостаточно. Функция FOO() в которой возник assert вызывается из многих мест, цепочка вызовов достаточно длинная, и нужно знать на каком именно этапе произошло формирование ошибочного набора параметров для FOO(). Кроме того место для логгирования сбоев ограничено. Но как вариант просто сохранять кадр стека (побольше) имеет место быть. В любом случае нужна ручная работа. По поводу возврата из функции не через POP - тоже верно, такое возможно, можно учесть и этот случай, но я в своем проекте такого не встречал (возможно это зависит от уровня оптимизации).
  12. Задача по обратной раскрутке стека вызовов у меня возникает регулярно. Понятно, что в режиме отладки за вас это делает отладчик, но часто нужно делать пост-анализ сбоев в рантайме. Ничего готового я не нашел, хотя возможно все лежит на поверхности. Сейчас я реализовал это через одно место (жутко процессоро- и компиляторо- зависисимо - IAR и Thumb-2). void assertSave ( void) { uint32_t sp; uint16_t * pc; uint32_t report[8]; uint32_t count; __ASM volatile ("mov %0, sp" : "=r" (sp) ); __ASM volatile ("mov %0, pc" : "=r" (pc) ); memset(report, 0, sizeof(report)); for (uint32_t i = 0; i < 8; i++) { while (1) { // check pc if (((uint32_t)pc < IFLASH_START_ADDRESS) || ((uint32_t)pc > IFLASH_END_ADDRESS)) break; // check sp if (((uint32_t)sp < IRAM_START_ADDRESS) || ((uint32_t)sp > IRAM_END_ADDRESS)) break; // find POP or POP.W if (((*pc & 0xFF00) == 0xBD00) || (*pc == 0xE8BD)) { // count = number of registers to be restored by POP command if (*pc == 0xE8BD) { count = (uint32_t)(*(pc + 1) & 0x1FFF); } else { count = (uint32_t)(*pc & 0x00FF); } count = count - ((count >> 1) & 0x55555555); count = (count & 0x33333333) + ((count >> 2) & 0x33333333); count = (((count + (count >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; // checking previous command is ADD SP,SP,XX if ((*(pc - 1) & 0xFF00) == 0xB000) { // count += size of the stack correction before POP count += (uint8_t)(*(pc - 1) & 0x00FF); } // getting stack frame of previous function sp += count << 2; // getting continue address of previous function pc = (uint16_t *)(*(uint32_t *)sp & 0xFFFFFFFE); sp += 4; // save address of CALLSTACK report[i] = (uint32_t)pc - 4; break; } pc += 1; } } // write to blackbox blackBoxWrite(report, sizeof(report)); } По сути я просматриваю от текущего PC до ближайшего возврата через POP или POP.W. По коррекции стека перед выходом определяю размер текущего фрейма стека с предположением что первым в стек компилятор кладет адрес возврата. Ну и дальше рекурсия. Возможно у кого-то есть более грамотное решение.
  13. Критерии совершенства в CubeMX?

    Да. Но это специфика очень большой компании с подразделениями по всему миру. Бамбук выполняет кроме сборки кучу дополнительной работы по фиксации релиза.