Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум разработчиков электроники ELECTRONIX.ru _ IAR _ Как отучить IAR использовать регистры FPU где не нужно?

Автор: jcxz Aug 18 2018, 20:25

Столкнулся с очень неприятным моментом в работе IAR:
В какой-то момент заглянул в листинг и увидел, что копируя структуру, IAR использует регистры FPU!
Хотя и рядом нет никаких операций с плавучкой. Просто есть структура, есть две переменных типа этой структуры и есть операция копирования одной переменной в другую (присваиванием, без memcpy()). И я вижу что IAR 7.80.4 лепит такой код (с оптимизацией и без):

Код
ADD      R2,SP,#+8
VLDM     R2,{D0-D3}
VSTM     R1,{D0-D3}

Что очень неприятно, ведь работа идёт под РТОС, в одной из задач ОС. В этой задаче нет никаких операций с плавучкой. Соответственно данная задача создаётся с указанием ОС что она не использует FPU. Соответственно ОС при переключении контекста с/в данную задачу не сохраняет/восстанавливает регистры FPU. Соответственно - будут разрушены регистры FPU в тех задачах, которые используют FPU (а также в тех, в коих IAR так же впихнул такое копирование через FPU).
Некоторые задачи в программе используют плавучку, значит полностью запретить FPU нельзя. Можно конечно сделать сохранение контекста FPU для всех задач вне зависимости от использования ими FPU, но не хотелось бы, так как все стеки задач придётся увеличить, увеличится время переключений контекста задач. Да и вообще - зачем? ОЗУ ведь не резиновая?

Как запретить IAR-у использовать регистры FPU для всего, кроме операций с плавучкой? Что-то в мануале не найду ничего про такое.... sad.gif(((((

Автор: Arlleex Aug 19 2018, 07:55

Цитата(jcxz @ Aug 18 2018, 23:25) *
Столкнулся с очень неприятным моментом в работе IAR...

Дык известное ж дело (вроде), что не только в IAR, оно везде так, думается мне. Keil также поступает в некоторых случаях, под Eclipse для Cortex-A тоже самое. Я не стал разбираться пока что досконально, почему код с применением регистров FPU будет работать быстрее. Но чую, что оно действительно так.

Цитата(jcxz @ Aug 18 2018, 23:25) *
Что очень неприятно, ведь работа идёт под РТОС, в одной из задач ОС. В этой задаче нет никаких операций с плавучкой. Соответственно данная задача создаётся с указанием ОС что она не использует FPU.

Ух ты! А что у Вас за ОС? Почему во FreeRTOS такой возможности нет crying.gif

Цитата(jcxz @ Aug 18 2018, 23:25) *
Как запретить IAR-у использовать регистры FPU для всего, кроме операций с плавучкой? Что-то в мануале не найду ничего про такое.... sad.gif(((((

Ну не знаю насчет IAR, просто с сайта ARM Вам пищу для размышлений хочу указать. Оно как раз Вам подходит. Запрещает использовать FPU везде, где не пахнет операциями плавучки.
http://electronix.ru/redirect.php?http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0491c/BABIBCGE.html&_ga=2.170441000.965661431.1534666318-730891758.1533144436

Автор: AlexandrY Aug 19 2018, 11:44

Цитата(jcxz @ Aug 18 2018, 23:25) *
Как запретить IAR-у использовать регистры FPU для всего, кроме операций с плавучкой? Что-то в мануале не найду ничего про такое.... sad.gif(((((

Вот это поворот!
Действительно при копировании 32-х и 64-х байтных структур IAR использует регистры FP сопроцессора.
И не лечится ничем.
Отключение оптимизации не помогает.
Просто запретить --fpu=none для отдельного файла компилятор не дает. Других опций и прагм нет.
Между тем в uCOS для портов на ARM под IAR повсеместно используется запрет на сохранение контекста FP.
В других осях тоже.

Автор: jcxz Aug 19 2018, 13:05

Цитата(Arlleex @ Aug 19 2018, 10:55) *
почему код с применением регистров FPU будет работать быстрее. Но чую, что оно действительно так.

Скорость копирования в данном случае меня не интересует.
Тем более что - копирование всего 32 байт, и редкое. А заплатить за это придётся значительным увеличением стеков всех задач и соответственно - увеличением времени переключения контекстов всех задач. Только проигрыш в результате. sad.gif

Цитата(Arlleex @ Aug 19 2018, 10:55) *
Ух ты! А что у Вас за ОС? Почему во FreeRTOS такой возможности нет crying.gif

Дык - поэтому и не использую FreeRTOS, потому что там многого полезного нет laughing.gif
У меня uCOS-II.

Цитата(Arlleex @ Aug 19 2018, 10:55) *
Ну не знаю насчет IAR, просто с сайта ARM Вам пищу для размышлений хочу указать. Оно как раз Вам подходит. Запрещает использовать FPU везде, где не пахнет операциями плавучки.
--no_allow_fpreg_for_nonfpdata

К сожалению IAR не понимает эту опцию. sad.gif sad.gif sad.gif

Цитата(AlexandrY @ Aug 19 2018, 14:44) *
Между тем в uCOS для портов на ARM под IAR повсеместно используется запрет на сохранение контекста FP.
В других осях тоже.

Вот именно!
Заметил только вчера эту пакость со стороны IAR-а. Сейчас думаю, что возможно какие-то случайные, редко-проявляющиеся баги, которые иногда возникают, могли быть вызваны этим.
Пока перевёл копирование структур на memcpy(). Но нет уверенности что IAR, при включённой оптимизации не станет шалить с регистрами FPU и в других местах, а не только при копировании структур. sad.gif

Автор: ih_ Aug 22 2018, 15:17

Цитата(jcxz @ Aug 18 2018, 23:25) *
Столкнулся с очень неприятным моментом в работе IAR:
...
Какой МК?

Автор: DASM Aug 22 2018, 16:37

Гм.. перекатил проект на юкосе на Гцц компилер - проблем не получил. Ну кроме выравнивания стека на 8, но там и для ИАР стояли директивы, сам виноват, не поставил аналогичные. Но чтобы с фпу засады.. гцц вроде не пакостил пока

Цитата(ih_ @ Aug 22 2018, 18:17) *
Какой МК?

Неужели много вариантов с фпу стало , кроме кортексов 4ф и выше (ну и А серия)?

Автор: jcxz Aug 22 2018, 20:04

Цитата(ih_ @ Aug 22 2018, 18:17) *
Какой МК?

Cortex-M4F

Цитата(DASM @ Aug 22 2018, 19:37) *
Гм.. перекатил проект на юкосе на Гцц компилер - проблем не получил. Ну кроме выравнивания стека на 8, но там и для ИАР стояли директивы, сам виноват, не поставил аналогичные. Но чтобы с фпу засады.. гцц вроде не пакостил пока

Да, как-то печально. До сих пор уважал IAR..... 05.gif

Автор: ViKo Aug 23 2018, 06:49

В тех задачах, где используется FPU, регистры сохранятся и восстановятся при входе и выходе. А в других... а сколько тех других? Одна?

Автор: Сергей Борщ Aug 23 2018, 07:39

QUOTE (ViKo @ Aug 23 2018, 09:49) *
В тех задачах, где используется FPU, регистры сохранятся и восстановятся при входе и выходе.
Если такие задачи имеют наивысший приоритет и не могут быть вытеснены задачами, которые не сохраняют, но иногда портят регистры сопроцессора - будет работать.

Автор: jcxz Aug 23 2018, 08:01

Цитата(ViKo @ Aug 23 2018, 09:49) *
В тех задачах, где используется FPU, регистры сохранятся и восстановятся при входе и выходе. А в других... а сколько тех других? Одна?

Не одна, а большинство. У меня FPU используется не где попало, а только там где нужно.

Цитата(Сергей Борщ @ Aug 23 2018, 10:39) *
Если такие задачи имеют наивысший приоритет и не могут быть вытеснены задачами, которые не сохраняют, но иногда портят регистры сопроцессора - будет работать.

Любая задача может быть вытеснена, вне зависимости от её приоритета, так как любая использует хотя-бы один объект синхронизации ядра (семафоры, мьютексы и т.п.).
К тому же назначение приоритетов должно делаться не по багам компилятора, а по требованиям прикладной задачи. Как можно назначить наивысший приоритет задаче, которая массивно выполняет операции с плавучкой (обработка данных) и убить этим работу всех реалтаймовых задач, например: драйверов устройств, которые не требуют большого времени выполнения, но требуют быстрой реакции на события в периферии?
Мои проекты насыщены разнообразной периферией и, соответственно, много драйверов устройств. Но при этом в паре-тройке мест нужно периодически обработать плотно данные на FPU (фильтрация).

Автор: ViKo Aug 23 2018, 08:19

Цитата(jcxz @ Aug 23 2018, 11:01) *
Не одна, а большинство. У меня FPU используется не где попало, а только там где нужно.

Нет, сколько задач с присвоением одной структуры другой? Может, компилятор неким образом держит под контролем такую ситуацию?

Автор: scifi Aug 23 2018, 08:45

Раскидать задачи по разным файлам и компилировать с разными ключиками: одни для CM3, другие - CM4F. Вероятно, линкер будет отказываться их скрестить, надо как-то побороть.

Автор: jcxz Aug 23 2018, 08:55

Цитата(ViKo @ Aug 23 2018, 11:19) *
Нет, сколько задач с присвоением одной структуры другой? Может, компилятор неким образом держит под контролем такую ситуацию?

Теперь уже ни одной. Прошерстил исходники и все такие места заменил на memcpy().

Цитата(scifi @ Aug 23 2018, 11:45) *
Раскидать задачи по разным файлам и компилировать с разными ключиками: одни для CM3, другие - CM4F. Вероятно, линкер будет отказываться их скрестить, надо как-то побороть.

Да, вариант. В крайнем случае видимо можно так и поступить.
Пока обошёлся memcpy() как менее травмирующим решением. И надеюсь что IAR-овцы не додумаются и внутренности memcpy() оптимизировать с помощью FPU... 05.gif
А то придётся библиотечный memcpy() заменять на свою ассемблерную реализацию.

Автор: Сергей Борщ Aug 23 2018, 09:14

QUOTE (jcxz @ Aug 23 2018, 11:01) *
Любая задача может быть вытеснена, вне зависимости от её приоритета, так как любая использует хотя-бы один объект синхронизации ядра (семафоры, мьютексы и т.п.).
При работе с объектом синхронизации задача не вытесняется в произвольном месте, а отдает управление с сохранением своего контекста (включая регистры сопроцессора).

QUOTE (jcxz @ Aug 23 2018, 11:01) *
К тому же назначение приоритетов должно делаться не по багам компилятора, а по требованиям прикладной задачи.
Естественно. Я отвечал на сообщение ViKo, где он утверждал, что достаточно сохранять регистры сопроцессора в "нужных" задачах, а остальные могут их портить.

Автор: jcxz Aug 23 2018, 09:34

Цитата(Сергей Борщ @ Aug 23 2018, 12:14) *
При работе с объектом синхронизации задача не вытесняется в произвольном месте, а отдает управление с сохранением своего контекста (включая регистры сопроцессора).

А какая разница? Контекст то ведь будет сохранять та же функция ОС, которая сохраняет и при вытеснении в тот же формат.
Или задача сама отдаёт управление, передавая свои регистры переключателю контекста, или она вытесняется ISR-ом, который кладёт часть её регистров в стек и потом если нужно передаёт переключателю контекста - разницы нет.

Автор: ih_ Aug 23 2018, 13:40

Цитата(jcxz @ Aug 23 2018, 12:34) *
А какая разница?...
Есть разница. У некоторых МК РОНы отображаются на память. И если в Вашем случае это так, то я хотел предложить создать по этому адресу volatile переменную, тогда компилятор не посягнул бы на эту область памяти - регистр.

Автор: AlexandrY Aug 23 2018, 13:41

Цитата(AlexandrY @ Aug 19 2018, 14:44) *
Между тем в uCOS для портов на ARM под IAR повсеместно используется запрет на сохранение контекста FP.

Ошибся.
В uCOS-III опция OS_OPT_TASK_SAVE_FP есть , но для порта под Cortex-M4 не применяется.
Т.е. если компилятор объявил макрос __ARMVFP__ , то все задачи без исключения сохраняют контекст fpu.
Другое дело, что в startup файлах из bsp может случайно не взводится флаг FPCA в регистре CONTROL, допустим проигнорен вызов __iar_program_start, и прерывания по умолчанию не сохраняют контекст fpu.

Эт в MQX версии community большая проблема, там такая опция работает и реально блокирует сохранение контекста fpu при переключении задач, а FPCA сознательно не взводится.
Так они ускоряют переключение контекста.

Экспериментировал как-то насколько сохранение контекста fpu увеличивает расход процессорного времени в обычном режиме. Не обнаружил существенной разницы.
Однако на быстрых прерываниях ядра обслуживающих сэмплирование в токовой цепи моторов менее чем за 1 мкс все становится критичней.
И тут MQX работает умнее чем uCOS и прочие FreeRTOS-ы.

Автор: Genadi Zawidowski Aug 23 2018, 14:02

А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Автор: AlexandrY Aug 23 2018, 14:29

Цитата(Genadi Zawidowski @ Aug 23 2018, 17:02) *
А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Беда в том, что флажок не говорит. laughing.gif

Автор: Сергей Борщ Aug 23 2018, 14:49

QUOTE (jcxz @ Aug 23 2018, 12:34) *
А какая разница? Контекст то ведь будет сохранять та же функция ОС, которая сохраняет и при вытеснении в тот же формат.
Пожалуй, вы правы. Тогда источником проблем остается только такой сценарий - задача, не сохраняющая регистры сопроцессора в момент копирования структуры через эти регистры прерывается другой задачей - либо законно использующей сопроцессор, либо такой же, которая в это время тоже решит скопировать структуру. Действительно, трудноотлавливаемый момент.

Автор: Genadi Zawidowski Aug 23 2018, 16:31

Цитата
флажок не говорит
Баг в ядре процессора?

Автор: jcxz Aug 23 2018, 20:01

Цитата(ih_ @ Aug 23 2018, 16:40) *
Есть разница. У некоторых МК РОНы отображаются на память. И если в Вашем случае это так, то я хотел предложить создать по этому адресу volatile переменную, тогда компилятор не посягнул бы на эту область памяти - регистр.

Я писал выше - у меня Cortex-M4. У него регистры никуда не отображаются.

Цитата(AlexandrY @ Aug 23 2018, 16:41) *
Т.е. если компилятор объявил макрос __ARMVFP__ , то все задачи без исключения сохраняют контекст fpu.
Другое дело, что в startup файлах из bsp может случайно не взводится флаг FPCA в регистре CONTROL, допустим проигнорен вызов __iar_program_start, и прерывания по умолчанию не сохраняют контекст fpu.

И FPCA и ASPEN и LSPEN (в FPCCR) у меня сброшены. И сброшены не случайно, поверьте про них я знаю. Сброшены потому что в ISR-ах в этом проекте плавучку не использую.
Я не знаю как там дела обстоят в uCOS-III, у меня uCOS-II. И читать и понимать исходники я думаю что умею. Эта функция в uCOS-II вызывается при переключении активной задачи:
CODE
#if (OS_CPU_HOOKS_EN > 0u) && (OS_TASK_SW_HOOK_EN > 0u)
void OSTaskSwHook (void)
{

#if (OS_CPU_ARM_FP_EN > 0u)
if ((OSTCBCur->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
OS_CPU_FP_Reg_Push(OSTCBCur->OSTCBStkPtr);
}

if ((OSTCBHighRdy->OSTCBOpt & OS_TASK_OPT_SAVE_FP) != (INT16U)0) {
OS_CPU_FP_Reg_Pop(OSTCBHighRdy->OSTCBStkPtr);
}
#endif

#if OS_APP_HOOKS_EN > 0u
App_TaskSwHook();
#endif
}
#endif

OS_CPU_HOOKS_EN, OS_TASK_SW_HOOK_EN, OS_CPU_ARM_FP_EN - все равны 1.
OS_CPU_FP_Reg_Push и OS_CPU_FP_Reg_Pop - тоже не пустые и делают то, что и полагается.
Обратите внимание на OS_TASK_OPT_SAVE_FP - именно этот флаг передаётся в аргументе prio (6-й бит) и говорит ОСи что задача юзает FPU и что нужно в сохраняемый/восстанавливаемый контекст для данной задачи включить регистры FPU.
Более того - одна из задач (Idle-задача) у меня имеет размер стека == 64 байта, т.е. - только-только чтобы сохранить регистры CPU, и если-бы туда сохранялись ещё и регистры FPU, то данные выше этого стека были бы снесены, а там весьма важные данные и они не портятся.
Да и отладчиком я пользоваться умею всё-таки... laughing.gif

Цитата(Genadi Zawidowski @ Aug 23 2018, 17:02) *
А что, флажок который говорит что FPU поюзали и его надо сохранить - отменили?

Когда FPU поюзала процедура копирования, то сохранять уже поздно.

Цитата(Сергей Борщ @ Aug 23 2018, 17:49) *
Пожалуй, вы правы. Тогда источником проблем остается только такой сценарий - задача, не сохраняющая регистры сопроцессора в момент копирования структуры через эти регистры прерывается другой задачей - либо законно использующей сопроцессор, либо такой же, которая в это время тоже решит скопировать структуру. Действительно, трудноотлавливаемый момент.

Да, Вы правы, именно в таком случае. Когда задача копирует через FPU, то значит она в этот момент активная, а все остальные задачи выгружены в память (все их копии регистров FPU все находятся в памяти). И естественно в этом случае она не может эти данные попортить. Но вот её данные - попортить могут.

PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).
Правда нет гарантии, что при копировании просто нескольких переменных, расположенных рядом, оптимизатор не захочет также прибегнуть к FPU. Или не копировании, а заполнении их константой. sad.gif

Автор: AlexandrY Aug 23 2018, 20:05

Цитата(jcxz @ Aug 23 2018, 22:41) *
Я не знаю как там дела обстоят в uCOS-III, у меня uCOS-II. И читать и понимать исходники я думаю что умею.

За uCOS-II я не писал, как раз чтобы вам предоставить возможность высказаться.

Все идет к тому что надо переходить на mbed. Самая нативная RTOS.

Автор: jcxz Aug 23 2018, 20:14

Цитата(AlexandrY @ Aug 23 2018, 23:05) *
Все идет к тому что надо переходить на mbed. Самая нативная RTOS.

А толку? как это поможет? IAR, узрев её исходники, сразу поостерегётся своевольничать? cool.gif

Автор: ViKo Aug 24 2018, 04:05

Цитата(jcxz @ Aug 23 2018, 23:01) *
PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).

А я сразу подумал о таком решении, но постеснялся предлагать очевидное.

Автор: Arlleex Aug 24 2018, 09:40

Цитата(jcxz @ Aug 24 2018, 00:01) *
PS: Кстати - Ваше замечание навело меня на мысль, что в качестве костыля можно на время копирования структур запрещать прерывания (критическая секция).

Именно так и пришлось делать в одном из проектов под ZYNQ, поскольку там компилятор в memcpy() использует FPU-регистры.
А где-то на сайте FreeRTOS даже читал, что действительно есть такой косяк. Вызываю в начале задачи vPortTaskUsesFPU() (даже забыл, что и во FreeRTOS можно указать задаче, использует ли она FPU или нет), и все равно все memcpy() защищаю критической секцией.

Автор: AlexandrY Aug 24 2018, 14:39

Цитата(jcxz @ Aug 23 2018, 23:14) *
А толку? как это поможет? IAR, узрев её исходники, сразу поостерегётся своевольничать? cool.gif

Да нет, просто в IAR 8.30 появился неплохой плагин под mbed. Можно уже нормально юзать. А там самый короткий переключатель контекста.

Кстати, в версии 8.30 у меня не получилось заставить использовать fpu при копировании структур.
Так что тревога отменяется.


Цитата(ViKo @ Aug 24 2018, 07:05) *
А я сразу подумал о таком решении, но постеснялся предлагать очевидное.

Если речь идет об ISR уровня ядра длительностью в 0.5 мкс и джитером 0.1 мкс , то такой путь неприемлем.
Хотя кому в голову придет в таких ISR копировать структуры!?

Автор: ViKo Aug 25 2018, 05:08

И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Автор: Arlleex Aug 25 2018, 06:42

Цитата(ViKo @ Aug 25 2018, 08:08) *
И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Это еще зачем?
Ведь структурные типы можно присваивать друг другу. Например
Код
typedef struct
{...}TMyStruct;

TMyStruct s1, s2;
...
s1 = s2;

Наглядно, читабельно и понятно. Без всяких приведений на int и поэлементных копирований...

Автор: jcxz Aug 25 2018, 06:44

Цитата(ViKo @ Aug 25 2018, 08:08) *
И зачем их копировать? Для малых структур я копирую поэлементно. А большие копирую через указатели на int, приведя к ним адреса структур исходной и назначения.

Умный оптимизатор может объединить ваши соседние копирования в более крупное одно. И получится то же самое. И не только структуры, можно предположить что любые рядом расположенные копирования смежных переменных: оптимизатору ведь по-барабану - единая это структура или просто несколько переменных, если адреса в памяти расположены смежно и нет volatile.
Здесь ключевой момент (как я показывал вначале): чтобы размер структуры был кратен 32 байтам - тогда видимо и используется FPU.

Автор: AlexandrY Aug 25 2018, 07:01

Цитата(jcxz @ Aug 25 2018, 09:44) *
Здесь ключевой момент (как я показывал вначале): чтобы размер структуры был кратен 32 байтам - тогда видимо и используется FPU.

Тут вы ошибаетесь, поэкспериментируйте еще. С размерами все сложнее.

Автор: jcxz Aug 25 2018, 07:10

Цитата(AlexandrY @ Aug 25 2018, 10:01) *
Тут вы ошибаетесь, поэкспериментируйте еще. С размерами все сложнее.

Поэкспериментировать в чём? Я же показал в каком случае FPU используется. В чём ошибаюсь?

Цитата(AlexandrY @ Aug 24 2018, 17:39) *
Кстати, в версии 8.30 у меня не получилось заставить использовать fpu при копировании структур.
Так что тревога отменяется.

В 8.30 есть более серьёзные баги. Так что использовать его не советую. Обсуждения были тут:
http://electronix.ru/redirect.php?https://electronix.ru/forum/index.php?showtopic=59841&view=findpost&p=1569519
http://electronix.ru/redirect.php?https://electronix.ru/forum/index.php?showtopic=147939&st=0

Автор: ViKo Aug 25 2018, 07:34

Цитата(Arlleex @ Aug 25 2018, 09:42) *
Это еще зачем?
Ведь структурные типы можно присваивать друг другу.

У меня одна структура является копией части другой. Вот для этого использую указатели. А целиком структуры одну в другую мне и копировать нет нужды.

Автор: jcxz Aug 25 2018, 08:03

Цитата(ViKo @ Aug 25 2018, 10:34) *
У меня одна структура является копией части другой.

А почему тогда она является копией, а не частью, что было-бы логично?

Автор: Arlleex Aug 25 2018, 08:31

Цитата(ViKo @ Aug 25 2018, 10:34) *
У меня одна структура является копией части другой. Вот для этого использую указатели. А целиком структуры одну в другую мне и копировать нет нужды.

Вот у меня, например, кусок хедера
Код
// структура калибровочных параметров аналогового окружения АЦП
typedef struct
{
    #define EEPROM_ADC_DEFAULT_ZERO      1.250000000
    double Zero;
    
    #define EEPROM_ADC_DEFAULT_REFERENCE 2.500000000
    double Reference;
    
    #define EEPROM_ADC_DEFAULT_SCALE     10.00000000
    double Scale;
}TADCTrueConstant;

// структура загрузочных параметров в EEPROM
typedef struct
{
    TADCTrueConstant ADC220V;
    TADCTrueConstant ADC220C1;
    TADCTrueConstant ADC220C2;
    TADCTrueConstant ADC220C3;
    TADCTrueConstant ADC220C4;
    TADCTrueConstant ADC220C5;
    TADCTrueConstant ADC200VA;
    TADCTrueConstant ADC200VB;
    TADCTrueConstant ADC200VC;
    TADCTrueConstant ADC200CA;
    TADCTrueConstant ADC200CB;
    TADCTrueConstant ADC200CC;
    
    TOneWireROM      OneWireROM[ONE_WIRE_MAX_DEVICES_ON_BUS];
    
    unsigned int     DeviceSignature[HW_MCU_SIGNATURE_SIZE];
    unsigned int     CRC32;
}TEEPROM;

Согласно Вашей логике, Вы элементы TEEPROM писали бы как подобие элементов TADCTrueConstant, после чего копировали поэлементно
Код
// структура калибровочных параметров аналогового окружения АЦП
typedef struct
{
    #define EEPROM_ADC_DEFAULT_ZERO      1.250000000
    double Zero;
    
    #define EEPROM_ADC_DEFAULT_REFERENCE 2.500000000
    double Reference;
    
    #define EEPROM_ADC_DEFAULT_SCALE     10.00000000
    double Scale;
}TADCTrueConstant;

// структура загрузочных параметров в EEPROM
typedef struct
{
    double Zero_ADC220V;
    double Reference_ADC220V;
    double Scale_ADC220V;
        ...
    double Zero_ADC200CC;
    double Reference_ADC200CC;
    double Scale_ADC200CC;
    
    // эту тоже заменить на содержимое TOneWireROM, чтобы получить копию
    TOneWireROM      OneWireROM[ONE_WIRE_MAX_DEVICES_ON_BUS];
    
    unsigned int     DeviceSignature[HW_MCU_SIGNATURE_SIZE];
    unsigned int     CRC32;
}TEEPROM;

или я что-то не так понял?
На мой взгляд способ, когда одни структуры содержат в себе другие структуры куда удобнее. И не надо поэлементно копировать.
Я присваиваю структуры структурам, если нужно что-то частично копирнуть, а если все нужно (например, в буфер отправки положить) - использую memcpy().

Автор: jcxz Aug 25 2018, 10:16

Цитата(Arlleex @ Aug 25 2018, 11:31) *
На мой взгляд способ, когда одни структуры содержат в себе другие структуры куда удобнее. И не надо поэлементно копировать.

Тот случай когда ощущаешь недостаток движка форума, не позволяющего ставить лайк или плюс сообщению... rolleyes.gif

Автор: Arlleex Aug 25 2018, 10:29

Цитата(jcxz @ Aug 25 2018, 13:16) *
Тот случай когда ощущаешь недостаток движка форума, не позволяющего ставить лайк или плюс сообщению... rolleyes.gif

Кстати, где-то мелькало вроде это предложение уже в соответствующем разделе. В общем-то было бы неплохо, ИМХО =)

Автор: ViKo Aug 25 2018, 10:31

Да, не так поняли.
У меня есть одна структура, состоящая из многих других, помельче. Я называю суперструктура. И есть другая, подобная части первой. В первой хранятся текущие режимы работы, во второй - предыдущее состояние некоторых нужных режимов. Когда нужно обновить вторую до первой, использую указатели. Когда нужно обновить отдельные элементы, обращаюсь непосредственно к ним.
Я не против копирования структур. Напоминаю о других способах, безглючных. biggrin.gif

Автор: jcxz Aug 25 2018, 12:16

Цитата(ViKo @ Aug 25 2018, 13:31) *
Я не против копирования структур. Напоминаю о других способах, безглючных. biggrin.gif

А я ещё раз напоминаю, что с точки зрения оптимизатора и 32 байта в виде одной структуры, и 32 байта состоящие из отдельных, но смежных переменных - это одно и то же.
Так что в почленном копировании ничего безопасного не вижу.

Автор: ViKo Aug 25 2018, 12:37

Цитата(jcxz @ Aug 25 2018, 15:16) *
А я ещё раз напоминаю, что с точки зрения оптимизатора и 32 байта в виде одной структуры, и 32 байта состоящие из отдельных, но смежных переменных - это одно и то же.
Так что в почленном копировании ничего безопасного не вижу.

При одиночном копировании int требуется один регистр, а не группа.

Русская версия Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)