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

_Desh_

Участник
  • Постов

    57
  • Зарегистрирован

  • Посещение

Весь контент _Desh_


  1. Методом проб и ошибок выяснил, что перезаписать данные по некоторому адресу можно, сначала исключив этот адрес: srec_cat.exe test_file_source.bin -binary -exclude 0x1C 0x20 -length-l-e 0x1C -o test_file.bin -binary Теперь по адресу 0x1C корректно записывается длина файла. Но теперь проблема записать по адресу 0x20 значение CRC. Если исключить диапазон 0x20-0x24, то в расчете CRC он не участвует, выдается предупреждение о том, что в данных есть прореха. В принципе, при сверке CRC программно внутри контроллера можно это учесть, но получается как-то некрасиво. Есть ли более элегантный способ прописать CRC в нужный адрес?
  2. Вопрос немного не об этом, но допустим. При попытке писать длину прошивки и CRC вместо неиспользуемых (несуществующих) векторов по заранее известному фиксированному адресу: srec_cat.exe test_file_source.bin -binary -length-l-e 0x1C -crc32-b-e 0x20 -o test_file.bin -binary srec_cat.exe выводит следующее сообщение об ошибке: srec_cat: test_file_source.bin: 0x0400: multiple 0x0000001C values (previous = 0x0C, this one = 0x00) Что это означает и как это исправить? Из документации ни черта не понятно, там есть почти такой же пример, и видимо он должен работать. P.S. Что означает ошибка примерно понял. Он мне хочет сказать, что я хочу какое-то ненулевое значение перезаписать новым значением (нулевым). Ну и что? Мне это и надо.
  3. Прошерстил форум и Интернет на предмет использования утилиты srec_cat.exe, но остались вопросы и непонятки. Мне надо добавить в конец прошивки ее CRC, с этим я справился: srec_cat.exe test_file_source.bin -binary -crc32-l-e -maximum-address test_file_source.bin -binary -o test_file.bin -binary Также хотелось бы перед формированием конечного файла прошивки увидеть в выводе IDE полученную CRC (или даже записать ее в отдельный файл). Это тоже можно сделать, например, так: srec_cat.exe test_file_source.bin -binary -fill 0xFF 0 0x400 -crop 0 0x400 -crc32-b-e 0x400 -crop 0x400 0x404 -o - -hex-dump Но как быть, если размер прошивки заранее неизвестен? Чтобы встроить вызов утилиты в IDE и полностью автоматизировать процесс, не вводя ручками каждый раз разные адреса. Во втором случае, если использовать, например, -crop -maximum-address test_file_source.bin -binary -maximum-address test_file_source.bin -binary -offset 4 вместо -crop 0x400 0x404 В консоль выводится полный дамп прошивки, а не 4 последние байта, как мне надо. Есть ли способ для утилиты srec_cat.exe указывать в качестве параметров, например, реальную длину файла, а не забивать магические константы?
  4. Если она обратится к библиотечным функциям, у которых исходные коды недоступны, у меня будут проблемы. Но наверняка они тоже решаемы, просто я пока не знаю как (оно мне сейчас не надо). Последний раз я пользовался Keil 4 с ARMCC и там можно было прямо в свойствах исходника мышкой указать размещение в конкретной области памяти. Либо так же с помощью атрибута, аналогичного GCC, если для отдельной функции или переменной. Но там еще можно было явно адрес указывать, например, __attribute__((at(0x20002000))). А в GCC так нельзя, только через линкер и секции.
  5. Знает. Я даже могу обратиться к переменным, указанным в скрипте линкера, в исходном коде, собственно, я это и делаю, когда копирую код функции - именно из скрипта я беру начальный и конечный адреса нужного участка кода. Нет, не допустимо. Я даже цитату из документации по компилятору для этого привел - он разместит мой код там, где ему указывает атрибут. Не останется, если я точно так же скопирую весь код и переменные, к которым идет обращение, туда же, при необходимости. Это неудобно, не спорю. В документации на линкер написано, что можно даже целиком объектный файл указывать для размещения в данной секции, но с этим я пока не разобрался. Копирование специально сделано перед вызовом функций, которые работают с периферией, как мне и посоветовали здесь. Я включил оптимизацию Os, затем O2, обычная функция и функция-обработчик прерывания работают из ОЗУ, поведение программы соответствует ожидаемому. Я не использую IAR, используемую среду разработки я указал в первом же посте первой же строкой.
  6. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes __attribute__((section(".RAMFUNC"))) void systick_config(void) { ... } Размещение секции указано здесь: RAMFUNC (rx) : ORIGIN = 0x20000000, LENGTH = 8K и здесь: .ramfunc : { ... *(.RAMFUNC.ISR) *(.RAMFUNC) *(.RAMFUNC*) ... } >RAMFUNC AT> FLASH
  7. Из атрибута, в котором указано, в какой области памяти находится код функции.
  8. Я обязательно разберусь. Просто я на STM32F4 с Миландровского 1986ВЕ1Т пересел. Там обязательно было код записи/стирания флэш-памяти в ОЗУ размещать. Перемещаемой таблицы там не было, потому что Cortex-M0/M1, это я уже сам затеял. Опыта у меня с STM32 мало.
  9. Нет, только страницу с основной программой. Я так и понял, что именно программист должен это гарантировать, вручную разместив все данные и функции, к которым будут обращения, в нужной области памяти.
  10. Я указал секцию, где будет размещена функция, при помощи линкера. В исходнике функции указал, что она размещается именно в этой секции. Затем самостоятельно скопировал код этой функции по соответствующему адресу RAM в стартапе. Что еще я должен сделать, чтобы эта функция разместилась там, где мне нужно?
  11. Верно, сейчас попробовал сделать как посоветовал АНТОХА, и все получилось. Просто вчера я свой вариант успел сделать и протестировать раньше, чем увидел его пост. Спасибо, что обратили мое внимание на это.
  12. Предполагаю стирать/писать флэш-память без запрета прерываний. Раньше я загрузку прошивки на лету ни разу не делал, опыта у меня мало. Сейчас я увидел неудобства, связанные с этим (начинал с Кейла, там гораздо проще делается размещение функций в ОЗУ), возможно в конце концов обойдусь простым запретом прерываний на время стирания/записи. Ну и сами-то функции стирания/записи по-любому придется в ОЗУ размещать. Так что осваивать все равно пришлось бы, пусть и не на примере обработчика.
  13. Нагуглил и сделал следующее (пусть это наверное всем кроме меня известный баян, напишу хотя бы для упорядочивания в своей голове). Объявил новую секцию RAMFUNC для размещения кода нужных мне функций в скрипте линкера. Пока выбрал 8 Кб, отрезав столько же от остальной RAM. MEMORY { CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K RAMFUNC (rx) : ORIGIN = 0x20000000, LENGTH = 8K RAM (xrw) : ORIGIN = 0x20002000, LENGTH = 120K FLASH (rx) : ORIGIN = 0x08020000, LENGTH = 128K } Описание секции между секциями .data и .bss: _siramfunc = LOADADDR(.ramfunc); .ramfunc : { . = ALIGN(4); _sramfunc = .; /* для копирования кода в startup-файле */ *(.RAMFUNC.ISR) *(.RAMFUNC) *(.RAMFUNC*) . = ALIGN(4); _eramfunc = .; /* для копирования кода в startup-файле */ } >RAMFUNC AT> FLASH В startup-файле вписал объявленные ранее переменные и добавил копирование кода по аналогии с уже имеющимся копированием данных .data и .bss. Как уже указывал уважаемый Forger, копировать код функций надо до вызова основной программы: .word _siramfunc .word _sramfunc .word _eramfunc ... CopyCodeRamFunc: ldr r3, =_siramfunc ldr r3, [r3, r1] str r3, [r0, r1] adds r1, r1, #4 LoopCopyCodeRamFunc: ldr r0, =_sramfunc ldr r3, =_eramfunc adds r2, r0, r1 cmp r2, r3 bcc CopyCodeRamFunc bl SystemInit bl main ... После этого осталось только объявить соответствующий атрибут для нужных мне функций. Для целей тестирования я сделал для одной обычной функции (инициализация Systick) и одного обработчика прерывания (того же Systick): __attribute__((section(".RAMFUNC"))) void systick_config(void) { ... } __attribute__((interrupt)) __attribute__((section(".RAMFUNC.ISR"))) void systick_handler_ram(void) { ... } Теперь обработчик работает корректно. Обычная функция тоже. Извините за простыню. Всем спасибо за подсказки.
  14. Подскажите пожалуйста хотя бы название. Что за мануал - на МК, на среду разработки, на сам GCC?
  15. Поведение остается прежним и при пустом обработчике. sp = 0x1000ffd0 (я разместил стек в области CCMRAM) lr = 0xfffffff9 Также наблюдал такую картину: содержимое окна дизассемблера кардинально различается в двух вариантах программы - с обработчиком во FLASH и с обработчиком в RAM. Для пустого обработчика во FLASH всего лишь: 080202ec: push {r7} 080202ee: add r7, sp, #0 А вот для обработчика в RAM полная белиберда, ничего похожего, просто непонятный набор инструкций. Как будто никакого копирования кода функции в ОЗУ не произошло. Разве для этого недостаточно просто указать рядом с объявлением/определением функции соответствующий атрибут?
  16. Попробовал перенести весь код в main с запретом прерываний на время инициализации - не помогло. Спасибо, но дело похоже не в этом. Первый-то раз в обработчик программа заходит как положено. Сбой при выходе из него. Порядок вызова в startup-файле - System_Init->__libc_init_array->main. Копирование всего, кроме таблицы, происходит до вызова System_Init. Для успокоения совести убирал вызов __libc_init_array - результат прежний.
  17. Разрабатываю в STM32CubeIDE. Контроллер STM32F407V. Так я копирую таблицу векторов в ОЗУ: #define VECTOR_EXCEPTION_NUM (16) /* Ссылка на таблицу векторов, размещенную в памяти Flash. Взята из файла * startup.s */ extern uint32_t g_pfnVectors[]; /* Массив для хранения адресов обработчиков прерываний, размещенных в RAM. */ static uint32_t vector_table_ram[94] __attribute__((section(".RAM"))) __attribute__((aligned(512))); void SystemInit(void) { uint32_t i = 0; /* Копируем таблицу векторов. */ for (i = 0; i < 94; i++) { vector_table_ram[i] = g_pfnVectors[i]; } /* Регистрация нового обработчика. */ vector_table_ram[VECTOR_EXCEPTION_NUM + SysTick_IRQn] = (uint32_t)&systick_handler_ram; /* VTOR. */ SCB->VTOR = (uint32_t)vector_table_ram; } Правильность копирования проверял в отладчике. Сама таблица разместилась по адресу 0x20000600, содержимое регистра VTOR соответствует. Обработчик прерывания, который я хочу разместить в ОЗУ: void systick_handler_ram(void) __attribute__((section(".RAM"))); void systick_handler_ram(void) { systick_inc_tick_1ms(); systick_flag = 1; } Обработчик успешно размещается по адресу 0х20000200, в новую таблицу векторов это значение вносится. Программа один раз заходит в обработчик, прошагивает инструкции до конца, а при выходе из него вылетает в HardFault. Если убрать из объявления systick_handler_ram атрибут размещения в секции RAM, обработчик размещается во FLASH, и прерывание работает - по прерыванию я завел счетчик и моргалку. Пробовал добавлять __attribute__((interrupt)) или __attribute__((interrupt("IRQ"))) - программа перестала даже заходить в обработчик - сразу в HardFault. Подскажите, пожалуйста, что я делаю не так? P.S. Пробовал делать так: vector_table_ram[VECTOR_EXCEPTION_NUM + SysTick_IRQn] = ((uint32_t)&systick_handler_ram) | 1UL; Ничего не меняется, компилятор добавляет единицу в младший разряд самостоятельно.
  18. Серия, поставщик подтвердил официально, периодика. На ближайшее будущее вопрос решен, продавили военных.
  19. Тогда, если я правильно понимаю, изделие верхнего уровня должно пройти испытания на свои ВВФ, на которых необходимо подтвердить эти требования. В этом случае, если испытания прошли успешно, к составной части вообще вопросов быть не должно.
  20. Нет, если микросхемы являются изделиями межотраслевого применения (входят в перечень МОП/ЭКБ). Импортные микросхемы таковыми не являются, хотя существуют некоторые типы ЭКБ ИП, которые имеют соответствующие утвержденные методики сертификационных испытаний, проводимые в специальных аттестованных испытательных организациях, и имеют даже какое-то подобие ТУ. Видел лично такие ТУ на некоторые ПЛИС Xilinx, например. Вообще, я не понял, как изделие, прошедшее испытания на свои ВВФ может без дополнительного подтверждения применяться в вышестоящем изделии с более жесткими ВВФ? Кто это пропустил?
  21. У меня претензий к реальной надежности нет (кроме того, что предприятия-изготовители ЭКБ порой умудряются гнать брак с приемкой ВП, а иногда даже и ОС/ОСМ). Претензии к стандартам. Сейчас начальство решает, надо ли писать в 22ЦНИИ (или как он там сейчас называется), видимо не хотят подставляться, я попробую все-таки продавить и написать.
  22. Отказ электромагнитного реле. Произошел на механике, которая по программе испытаний шла после климатики. Климатику изделие выдержало. Отказы ПКИ иногда бывали и раньше, на других этапах. Просто до чтения ТУ вояками дошло впервые. В данном конкретном случае (на мой взгляд) надо победить в первую очередь нормативы. Я прекрасно понимаю, что теоретически причиной может быть все, что угодно, например, снижение надежности электрического контакта обмотки реле на минусе и последующее окончательное разрушение на механике, но на моей практике ни один элемент на минус 65 не умирал. Умирали одиночные контакты в соединителях, умирала некачественная пайка, умирала некачественная металлизация переходных отверстий. Даже обычные буржуйские микросхемы в пластике работали и не жужжали (бывало, ставили эксперименты). Согласен, что в принципе это ничего не гарантирует. Просто хотел познакомиться с опытом других людей, которые делают аппаратуру на честные минус 65 - как они обосновывают применение ЭРИ или какие конструктивные решения им приходится использовать (и приходится ли). Лично на мой взгляд (не претендую на истину), в нормативах имеется конкретное неустранимое противоречие - если мой прибор должен в выключенном состоянии выдерживать минус 65, почему подавляющее большинство отечественных ЭРИ категории качества ВП по своим нормативам должны обеспечивать только минус 60? Как я буду обеспечивать термостатирование средствами самого прибора, если он выключен и выдерживается в течение нескольких суток, например?
  23. Предельная температура при более вдумчивом чтении документации обнаружилась в ОТУ. Она совпадает с рабочей пониженной и, в соответствии с этими же ОТУ, при совпадении температур испытания допускается проводить только на рабочую. Так-то буржуи тоже на industrial в пластиковых корпусах дают температуру хранения минус 55 или даже минус 65 при рабочей минус 40.
×
×
  • Создать...