Jump to content
    

Слабость оптимизатора IAR

16 hours ago, jcxz said:
unsigned Tst(unsigned const *p)             
{                                           
        _Z3TstPKj: (+1)                     
 0xB510             PUSH     {R4,LR}        
 0x4602             MOV      R2,R0          
  int n = 32;                               
  unsigned j = 0;                           
 0x2000             MOVS     R0,#+0         
 0x2120             MOVS     R1,#+32        
 0xF04F 0x34FF      MOV      R4,#+4294967295
  do j |= *p++ ^ -PFLASH_CLEAN;             
        ??Tst_0: (+1)                       
 0xF852 0x3B04      LDR      R3,[R2], #+4   
 0x4063             EORS     R3,R4,R3       
 0x4318             ORRS     R0,R3,R0       
  while (--n);                              
 0x1E49             SUBS     R1,R1,#+1      
 0xD1F9             BNE.N    ??Tst_0        
  return j;                                 
 0xBD10             POP      {R4,PC}        
}                                           

Пробовал компилить этот же код GCC v12.2.0 - там всё ок:

0000 0346        mov r3, r0                 
0002 00F18002    add r2, r0, #128           
0006 0020        movs  r0, #0               
               .L2:                         
0008 53F8041B    ldr r1, [r3], #4           
000c 9A42        cmp r2, r3                 
000e 60EA0100    orn r0, r0, r1             
0012 F9D1        bne .L2                    
0014 7047        bx  lr                     

 

Неужто IAR-овцы до сих пор так и не освоили систему команд Thumb-2??? :sad:

Или может более новые версии всё-таки поумнели?

У IAR в вашем случае всё нормально с оптимизацией, образцовая. А вы подумайте...

Edited by pyroman

Share this post


Link to post
Share on other sites

1 минуту назад, pyroman сказал:

У IAR в вашем случае всё нормально с оптимизацией. А вы подумайте...

Над чем думать-то?

"Нормально" - это ставить 3 команды вместо одной? Странные у вас понятия нормальности..... :unknw:

Share this post


Link to post
Share on other sites

27 minutes ago, jcxz said:

Над чем думать-то?

"Нормально" - это ставить 3 команды вместо одной? Странные у вас понятия нормальности..... :unknw:

Нормально. В этом случае...

Share this post


Link to post
Share on other sites

14 часов назад, Arlleex сказал:

Ясно. Ресурс экономите (и время).

4 часа назад, VladislavS сказал:

А потом вспоминаешь про 100K циклов записи и смену прошивки несколько раз в год в первые пару лет эксплуатации и становится грустно 😅

Да - совсем забыл: Ресурс флеши экономится моим алгоритмом весьма существенно. Критики видимо не задумывались над возможностью, что в момент когда пришло обновление прошивки (например по сети передачи данных), устройство может иметь нестабильное питание. И постоянно сбрасывается, через произвольное количество секунд. Что будет в этом случае? В этом случае мой алгоритм отработает корректно. Только медленнее естественно. И потратит ровно столько же ресурса флеши, как если бы питание было стабильным. А что же будет если всегда тупо стирать сектора флешь и всегда писать? В таком случае - первое же обновление прошивки намертво убьёт флешь МК, протерев её до дыр.

В реальной моей практике на позапрошлой работе у нас были заказчики, у которых было множество постоянно включенных наших устройств (счётчиков э/энергии). И подключенных к сети сбора. Но имеющих постоянно дергающееся питание. Заказчика это нисколько не волновало, так как в данный момент этот счётчик не используется, а просто висит на проводах (просто питающий фидер от ячейки подстанции ничего не питает). Факт постоянных перезагрузок мы обнаруживали, когда анализировали журналы работы счётчика. Заказчику это нисколько не мешает. Но что будет, если по такой сети сбора пройдёт обновление прошивки счётчиков, а алгоритм обновления реализован тупо? При тупом алгоритме, счётчик 100500 раз запустит процедуру обновления прошивки, 1000+ раз сотрёт флешь и убьёт её. С моим алгоритмом - не убьёт. Прошьётся в конце концов нормально. Пусть и дольше.

С такой целью этот алгоритм и был разработан.

Share this post


Link to post
Share on other sites

1 час назад, jcxz сказал:

Критики видимо не задумывались над возможностью, что в момент когда пришло обновление прошивки (например по сети передачи данных), устройство может иметь нестабильное питание.

А еще подлые мыши-диверсанты грызут провода, ага🙂
 

1 час назад, jcxz сказал:

При тупом алгоритме, счётчик 100500 раз запустит процедуру обновления прошивки, 1000+ раз сотрёт флешь и убьёт её.

Ну и супер - протрут до дыр, придут просить отремонтировать, попутно пусть чинят перебои питания, которые не иначе, как целенаправленные диверсии.

P.S. Я делал загрузчики в том числе и с проверкой содержимого нового сектора с содержимым флешки. Она, правда, гораздо проще (без всяких пометок и битовых карт): пришел блок данных на обновление, я считываю содержимое сектора флешки - если совпадает, иду дальше (ничего не делаю). Если не совпадает - откатываюсь до границы сектора, стираю, запрашиваю данные по откатанной границе - шуршу дальше.

Share this post


Link to post
Share on other sites

23 минуты назад, Arlleex сказал:

Ну и супер - протрут до дыр, придут просить отремонтировать, попутно пусть чинят перебои питания, которые не иначе, как целенаправленные диверсии.

Нет, они просто пришлют счётчик производителю с рекламацией - "самопроизвольно вышел из строя при штатной работе". И будут правы. Так как счётчик должен корректно работать при любых сбоях питания. И обновления по сети сбора данных в любой момент - тоже обычное явление.

23 минуты назад, Arlleex сказал:

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

А если страница не совпадает, но можно записать её без стирания (так как во флешь - стёртое содержимое)? У вас будет лишнее стирание сектора. А если питание дёргается - так и протрёте сектор до дыры.  :unknw:

Кроме того - проще, когда у вас образ не шифрованный. А у меня - образ шифрованный AES256. И большой - ОЗУ на весь образ не хватит. А значит - откатиться всего лишь до границы сектора не получится. Нужно запускать процесс чтения/дешифровки от самого начала.

Вот для того и битовые карты. Чтобы сперва сделать все сравнения, составить "план работ" так сказать, а потом - выполнять его попунктно. Так требуется всего 2 цикла прохода/дешифровки образа. И минимум стираний/записей флеши.

Share this post


Link to post
Share on other sites

38 минут назад, jcxz сказал:

А если страница не совпадает, но можно записать её без стирания (так как во флешь - стёртое содержимое)? У вас будет лишнее стирание сектора. А если питание дёргается - так и протрёте сектор до дыры.  :unknw:

Нет конечно - если минимальное слово записи (16 бит) полностью 0xFFFF, т.е. его можно записать без стирания - я пишу. Поэтому лишних стираний не будет.

38 минут назад, jcxz сказал:

И большой - ОЗУ на весь образ не хватит. А значит - откатиться всего лишь до границы сектора не получится. Нужно запускать процесс чтения/дешифровки от самого начала.

А. Вы про шифровку. Ну опять же - нельзя шифровать небольшие куски (блоки), умещающиеся в достаточный объем ОЗУ?

Share this post


Link to post
Share on other sites

1 час назад, Arlleex сказал:

Нет конечно - если минимальное слово записи (16 бит) полностью 0xFFFF, т.е. его можно записать без стирания - я пишу. Поэтому лишних стираний не будет.

Ну вот шли вы шли по сектору - всё или совпадало или были 0xFFFF - писали, и вдруг - не совпадающее и не 0xFFFF! Нужно откатываться и стирать и писать по новой. Т.е. - какие-то данные будете писать по два раза, тормозя и тратя ресурс.

1 час назад, Arlleex сказал:

А. Вы про шифровку. Ну опять же - нельзя шифровать небольшие куски (блоки), умещающиеся в достаточный объем ОЗУ?

В смысле - не шифровать как единый файл, а шифровать кусками по объёму свободного ОЗУ?

Так вроде - минусы очевидны:

1. Сперва всё равно нужно всё прочитать и проверить валидность прошивки. Т.е. - один цикл дешифрующий все куски, с подсчётом SHA-256 всего образа.

2. Затем - какого размера куски шифровать? Сегодня алгоритм работает на одном МК, завтра на другом: размеры свободного ОЗУ - разные; размеры секторов стирания - тоже разные. И в МК могут быть сектора размера больше свободного размера ОЗУ (сектора 128/256 КБ в МК - не редкость уже). Придётся и утилиты шифрования переписывать каждый раз и сам алгоритм дешифровки. А в чём бонус такого подхода? Всё равно - раз сектор может быть больше размера свободной ОЗУ - то один фиг придётся карты страниц строить. Только уже не на весь образ, а на каждый сектор по-отдельности. Получится ещё сложнее чем у меня.

У меня всего 2 прохода дешифровки - сперва сбор данных/построение карт, потом - прошивка страниц по карте. И ОЗУ требуется минимум - только на карты страниц (256-байтных) и на один сегмент дешифровки AES.

3. Увеличится размер образа - каждому куску нужен будет заголовок. Заголовок не кратный размеру страницы - опять проблемы с выравниванием.

4. У меня нет полной уверенности, что общая криптостойкость образа прошивки не уменьшится при таком способе шифрования. При шифровании данные для каждого последующего сегмента шифрованного образа зависят от предыдущего - XOR-ятся и шифруются. Если шифровать независимыми кусками - как минимум каждому куску потребуется заголовок с какими-то случайными данными. Кусок станет некратного странице размера (странице внутренней флешь или странице внешней флешь) и т.д.

5. Усложнение утилит шифрования/проверки образов прошивок.

 

Вобщем - в чём плюсы такого метода? непонятно. Только хуже станет. имхо.

Share this post


Link to post
Share on other sites

Блочный шифр с размером блока целое кол-во раз укладывающимся в странцу.

Share this post


Link to post
Share on other sites

1 минуту назад, jcxz сказал:

Ну вот шли вы шли по сектору - всё или совпадало или были 0xFFFF - писали, и вдруг - не совпадающее и не 0xFFFF! Нужно откатываться и стирать и писать по новой.

Ну да. А как иначе? Если хочется записать в не стертое слово пусть даже наполовину грязного сектора (в котором уже лежат данные), то этот сектор в любом случае придется стирать.

Share this post


Link to post
Share on other sites

16 минут назад, VladislavS сказал:

Блочный шифр с размером блока целое кол-во раз укладывающимся в странцу.

И что? Предлагаете заголовок перед каждой независимой шифруемой частью сделать равным размеру страницы? В этом случае суммарный размер образа сильно вырастет. О чём я выше писал.

4 минуты назад, Arlleex сказал:

Ну да. А как иначе? Если хочется записать в не стертое слово пусть даже наполовину грязного сектора (в котором уже лежат данные), то этот сектор в любом случае придется стирать.

Ну вот у вас и получается, что некоторые страницы будут писаться по 2 раза. У меня - всегда только 1 раз. Каждая страница пишется не более одного раза.

"Иначе" - сразу построить карту стираний/записей. Что я и делаю.

Share this post


Link to post
Share on other sites

4 минуты назад, jcxz сказал:

"Иначе" - сразу построить карту стираний/записей. Что я и делаю.

Построили. Выявили, что надо стереть память. Стерли. Стали писать - выключили питание. Включили. Начали снова пытаться строить карту, видим, что сектор записан не полностью, и одно из слов не совпадает с тем, которой лежит в образе. Т.е. слово флешки уже не перезаписать. Т.е. надо стирать сектор. У меня то же самое.

Share this post


Link to post
Share on other sites

20 минут назад, Arlleex сказал:

Построили. Выявили, что надо стереть память. Стерли. Стали писать - выключили питание. Включили. Начали снова пытаться строить карту, видим, что сектор записан не полностью, и одно из слов не совпадает с тем, которой лежит в образе. Т.е. слово флешки уже не перезаписать.

Почему не перезаписать? Делаем OR или AND - и просто дописываем поверх.

20 минут назад, Arlleex сказал:

Т.е. надо стирать сектор. У меня то же самое.

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

Share this post


Link to post
Share on other sites

24 минуты назад, jcxz сказал:

Почему не перезаписать? Делаем OR или AND - и просто дописываем поверх.

В STM если я в ячейку, которая имеет значение != 0xFFFF (стертое), попытаюсь "дописать" данные, то контроллер покажет кукиш, и ничего не запишет.

Если в Вашем МК флешка умеет дописывать - отлично. Но тогда и мой алгоритм мог бы пройтись 1 раз.

И вообще в контроллерах флешки с ECC дописывать в гранулу, охраняемую ECC, нельзя (если специально разработчики не заморочились и каким-то чудом не делают перезапись ECC при дозаписи основной гранулы памяти).

Share this post


Link to post
Share on other sites

25 минут назад, Arlleex сказал:

В STM если я в ячейку, которая имеет значение != 0xFFFF (стертое) попытаюсь "дописать" данные, то контроллер покажет кукиш, и ничего не запишет.

Это в ячейку, запись которой полностью завершилась. Т.е. - к которой в конец были добавлены ECC-биты.

Но вы же говорите про случай сбоя питания? А в этом случае вангую - какая-то часть данных успела записаться, остальная - нет. И ECC-биты ещё не записаны (имеют стёртое состояние). А значит запись "поверх" по идее - должна пройти.

25 минут назад, Arlleex сказал:

Если в Вашем МК флешка умеет дописывать - отлично. Но тогда и мой алгоритм мог бы пройтись 1 раз.

Ещё раз ваш алгоритм:

Сравниваем страницу 0: нет изменений? Ничего не делаем.

Сравниваем страницу 1: есть изменения? Но можно записать без стирания. Пишем.

Сравниваем страницы 2...P-2: нет изменений? Ничего не делаем.

Сравниваем страницу P-1: есть изменения? И нельзя записать без стирания. Нужно стирать весь сектор, а потом писать заново.

Вот здесь у вас страница 1 пишется 2 раза. Даже без всяких сбоев питания.

А если таких страниц будет - с 0-й по (P-2)-ю? Вы все эти страницы запишете по 2 раза.

25 минут назад, Arlleex сказал:

И вообще в контроллерах флешки с ECC дописывать в гранулу, охраняемую ECC, нельзя (если специально разработчики не заморочились и каким-то чудом не делают перезапись ECC при дозаписи основной гранулы памяти).

Ещё раз - если эти самые ECC-биты записаны. Но если как вы говорите - был сбой питания, и даже биты данных не успели записаться, то видимо биты ECC должны быть стёртыми? Почему тогда не запишется?

И вы уверены - что запись невозможна если ECC есть? По моим экспериментам - запись проходит нормально, только потом читается мусор из-за неверного ECC-контроля. Но это же не мешает писать поверх.

 

PS: Вообще тестил когда-то свой алгоритм очень жёстко - с многократными случайными перезагрузками - сбоев не было ни разу. А ECC в XMC имеется. И даже ещё более жёсткая, чем в STM.

ЗЫ: Где-то в RM XMC видел явное утверждение о том, что при программировании флешь, байты страницы пишутся последовательно - один за другим: от 0-го байта к последнему. Очевидно ECC-биты должны добавляться уже после последнего байта данных. В XMC в API программирования flash использую постраничный режим программирования.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...