Выполнение кода из ОЗУ в STM32

Недавно я начал программировать на ядерной плате STM32F4. Я только что понял, что программирование во флеш-память возможно только ограниченное количество раз (хотя это немало, но это оценочная плата, и ее можно будет программировать снова и снова для разработки различных проектов). После этого я где-то читал, что можно напрямую программировать в ОЗУ вместо флэш-памяти, но не смог найти никакой технической информации об этом.

Кто-нибудь знает, как изменить компоновщик / make-файл, чтобы скомпилировать и связать программу, которая будет выполняться с начального адреса ОЗУ, а не с флэш-памяти?

ps: я использую сгенерированные коды STM32CubeMX для системной рабочей среды и скрипт для создания make-файла для проекта.

Более серьезная проблема заключается в том, как вы ожидаете, что код попадет в оперативную память. Вам потребуется какое-то соединение с другим устройством, которое предоставляет код после сброса (или загрузить код в ОЗУ из флэш-памяти, но это не дает цели (хотя вы можете уменьшить количество операций записи во флэш-память, сжав код во флэш-памяти)).   —  person Nixmd    schedule 05.03.2017

Флэш-программирование, вероятно, исчисляется многими тысячами, если не десятками тысяч, вы уже достигли этого?   —  person Nixmd    schedule 05.03.2017

Помимо отличного ответа @FreddieChopin, два других момента о выполнении из ОЗУ на STM32; 1) Для большинства частей размер ОЗУ намного меньше, чем у флэш-памяти, поэтому вы должны ограничить размер своего приложения. 2) При работе с флэш-памятью доступ к данным и инструкциям для чтения и записи осуществляется по отдельным шинам, а флэш-память имеет ускоритель, что обеспечивает полную указанную производительность 1,25DMIPS / МГц. Запуск из оперативной памяти вызывает конкуренцию на шине за доступ к данным и инструкциям и значительно замедляет выполнение.   —  person Nixmd    schedule 05.03.2017

См. также:  Сбой развертывания Azure Pipeline в службе веб-приложений с отсутствующим обязательным свойством OutputPath

В том маловероятном случае, если износ вспышки станет проблемой до того, как произойдет какое-то другое бедствие, такое как просто неправильная установка платы или повреждение электростатическим разрядом, просто купите другую плату — относитесь к ней как к расходному материалу. Кроме того, как вы думаете, как долго вы будете использовать это поколение STM32 в будущих проектах? Технологии развиваются, затраты падают, а поставщики заменяют устаревшие детали, так что вы, вероятно, выберете другой процессор для будущих проектов.   —  person Nixmd    schedule 05.03.2017

Какое максимальное количество операций записи и сколько стоит новый микроконтроллер и / или плата оценки? Вероятно, имеет смысл просто не беспокоиться об этом и либо заменить микроконтроллер, либо просто купить новую плату, если вы когда-нибудь дойдете до этого.   —  person Nixmd    schedule 06.03.2017

Я программировал stm32 flash снова и снова больше года, и он до сих пор работает. Сколько работы вы планируете делать над одной конкретной доской? Как только вы закончите с ним работать, он многократно окупился.   —  person Nixmd    schedule 01.08.2018

Просто комментарий к призракам в комнате, но я наткнулся на этот вопрос через Google, так как мне нужна была та же информация, что и OP; но в моем случае я планирую динамически перезагружать STM32 с главного контроллера (ESP32) в зависимости от требований к работе в реальном времени во время выполнения (следовательно, потенциально многие тысячи перепрограмм в течение срока службы) — в то время как точки скептиков были совершенно справедливы для ОП. Я, со своей стороны, благодарен исходному вопросу, и, следовательно, ответы никогда не исчезли из-за предыстории постановки вопроса.   —  person Nixmd    schedule 13.10.2020

Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 2
  1. Nixmd

    Если вы недавно начали ее использовать, то у вас есть еще много времени до того, как вспышка износится. Вы можете получать ошибки переполнения диска, просто отключите и снова подключите плату. У меня эти штуки годами и вспышка еще не износилась. Не сказать, что это невозможно сделать, это возможно, но вы вряд ли сможете это сделать, если только не написали программу для очистки флэш-памяти, которая ее изнашивает.

    Вам понадобится openocd (или какой-нибудь другой отладчик, возможно, ваша IDE предоставляет это, я их не использую, поэтому не могу помочь). Инструменты openocd и gnu легко найти, поэтому мы рассмотрим их.

    Из правильного каталога или скопировав эти файлы из openocd

    openocd -f stlink-v2-1.cfg -f stm32f4x.cfg
    

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

    должен заканчиваться примерно так и не выходить обратно в командную строку

    Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
    

    В другом окне

    telnet localhost 4444
    
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    Open On-Chip Debugger
    > 
    

    В этом окне вы можете остановить процессор

    > halt
    stm32f4x.cpu: target state: halted
    target halted due to debug-request, current mode: Thread 
    xPSR: 0x61000000 pc: 0x080000b2 msp: 0x20000ff0
    > 
    

    Полноразмерные процессоры ARM ваша точка входа — это инструкция, и вы просто начинаете ее выполнять. Cortex-m использует таблицу векторов, которую вы не можете просто разветвлять.

    .thumb_func
    .global _start
    _start:
    stacktop: .word 0x20001000
    .word reset
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    .word hang
    
    .thumb_func
    reset:
        bl notmain
        b hang
    
    .thumb_func
    hang:   b .
    

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

    sram.s

    .cpu cortex-m0
    .thumb
    
    .thumb_func
    .global _start
    _start:
        ldr r0,stacktop
        mov sp,r0
        bl notmain
        b .
    
    .align
    stacktop: .word 0x20001000
    
    .thumb_func
    .globl PUT32
    PUT32:
        str r1,[r0]
        bx lr
    
    .thumb_func
    .globl GET32
    GET32:
        ldr r0,[r0]
        bx lr
    

    notmain.c

    void PUT32 ( unsigned int, unsigned int );
    unsigned int GET32 ( unsigned int );
    
    int notmain ( void )
    {
        unsigned int ra;
        ra=GET32(0x20000400);
        PUT32(0x20000404,ra);
        PUT32(0x20000400,ra+1);
        return(0);
    }
    

    sram.ld

    MEMORY
    {    
        rom : ORIGIN = 0x08000000, LENGTH = 0x1000
        ram : ORIGIN = 0x20000000, LENGTH = 0x1000
    }
    
    SECTIONS
    {
        .text : { *(.text*) } > ram
        .rodata : { *(.rodata*) } > ram
        .bss : { *(.bss*) } > ram
    }
    

    в основном замените ссылки на ROM на RAM. (ваш сценарий компоновщика, если gnu, вероятно, намного сложнее, чем этот, но он работает нормально, можно добавить сюда .data по мере необходимости).

    arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
    arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
    arm-none-eabi-ld -o notmain.flash.elf -T flash.ld flash.o notmain.o
    arm-none-eabi-objdump -D notmain.flash.elf > notmain.flash.list
    arm-none-eabi-objcopy notmain.flash.elf notmain.flash.bin -O binary
    arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 sram.s -o sram.o
    arm-none-eabi-ld -o notmain.sram.elf -T sram.ld sram.o notmain.o
    arm-none-eabi-objdump -D notmain.sram.elf > notmain.sram.list
    arm-none-eabi-objcopy notmain.sram.elf notmain.sram.hex -O ihex
    arm-none-eabi-objcopy notmain.sram.elf notmain.sram.bin -O binary
    

    моя сборка как flash-версии, так и sram-версии программы.

    Итак, теперь у нас есть Telnet на сервере openocd, процессор остановлен, давайте посмотрим на место в памяти и изменим его

    > mdw 0x20000400
    0x20000400: 7d7d5889 
    > mww 0x20000400 0x12345678
    > mdw 0x20000400           
    0x20000400: 12345678 
    

    и запустите нашу новую программу на основе sram

    > load_image /path/to/notmain.sram.elf
    64 bytes written at address 0x20000000
    downloaded 64 bytes in 0.008047s (7.767 KiB/s)
    > resume 0x20000001
    

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

    > halt
    stm32f4x.cpu: target state: halted
    target halted due to debug-request, current mode: Thread 
    xPSR: 0x41000000 pc: 0x20000008 msp: 0x20001000
    > mdw 0x20000400 10
    0x20000400: 12345679 12345678 ce879a24 fc4ba5c7 997e5367 9db9a851 40d5083f fbfbcff8 
    0x20000420: 035dce6b 65a7f13c 
    > 
    

    Итак, программа запустилась, программа считывает 0x20000400, сохраняет его с шагом 0x20000404 и сохраняет его до 0x20000400, и все это она сделала.

    > load_image /path/to/notmain.sram.elf
    64 bytes written at address 0x20000000
    downloaded 64 bytes in 0.008016s (7.797 KiB/s)
    > resume 0x20000000
    > halt
    stm32f4x.cpu: target state: halted
    target halted due to debug-request, current mode: Thread 
    xPSR: 0x41000000 pc: 0x20000008 msp: 0x20001000
    > mdw 0x20000400 10                           
    0x20000400: 1234567a 12345679 ce879a24 fc4ba5c7 997e5367 9db9a851 40d5083f fbfbcff8 
    0x20000420: 035dce6b 65a7f13c 
    > 
    

    так что нам не нужно было указывать начальный адрес с одним, что вы делаете с BX, они должны просто вставить адрес прямо в компьютер и / или сделать для нас правильные вещи.

    Если бы вы только изменили свой сценарий компоновщика, чтобы заменить ромы на бараны.

    20000000 <_start>:
    20000000:   20001000
    20000004:   20000041
    20000008:   20000047
    2000000c:   20000047
    20000010:   20000047
    20000014:   20000047
    20000018:   20000047
    2000001c:   20000047
    20000020:   20000047
    20000024:   20000047
    20000028:   20000047
    2000002c:   20000047
    20000030:   20000047
    20000034:   20000047
    20000038:   20000047
    2000003c:   20000047
    
    20000040 <reset>:
    20000040:   f000 f806   bl  20000050 <notmain>
    20000044:   e7ff        b.n 20000046 <hang>
    

    вы можете использовать адрес 0x20000041 в качестве точки входа (возобновить 0x20000041), но сначала вам нужно разобраться с указателем стека.

    Делая что-то вроде этого

    > reg sp 0x20001000
    sp (/32): 0x20001000
    > reg sp
    sp (/32): 0x20001000
    > resume 0x20000041
    

    Обратите внимание, что RAM на тезисах быстрее, чем ROM, и не требует состояний ожидания, поскольку вы увеличиваете тактовую частоту, поэтому, если вы увеличиваете тактовую частоту и отлаживаете только в RAM, он может выйти из строя при переключении на прошивку, если вы не запомнили установить состояния ожидания вспышки … Кроме этого и имея значительно меньше места для программ, вы можете разрабатывать в оперативной памяти весь день, если хотите.

    Одна приятная особенность заключается в том, что вы можете останавливаться и повторно загружаться. Я не знаю на этом устройстве / отладчике, если вы включаете кеш (у некоторых cortex-m4 есть кеш, если не у всех), вы должны быть осторожны, чтобы убедиться, что он выключен, когда вы меняете программы. запись в память — это операция с данными. Получение инструкций — это операция выборки инструкций, которая может попасть в кэш инструкций, если вы выполните некоторую инструкцию по адресу 0x20000100, и она будет кэширована в I-кеше. затем вы прекращаете использование отладчика, затем пишете новую программу, включая адреса в кеше (0x20000100), когда вы запускаете ее, кеш I не был сброшен, поэтому вы будете запускать смесь предыдущих программ в кеше и новую программу в данных, которые это в лучшем случае катастрофа. Поэтому либо никогда не включайте кеши при таком запуске, либо придумайте решение этой проблемы (очистите кеши перед остановкой программы, используйте кнопку сброса для сброса процессора между запусками, выключением и т. Д.).

    Вы уверены, что код andcs на процессоре только для большого пальца? person Nixmd; 05.03.2017

    нет такой вещи, как thumb2 только. thumb2 — это просто расширение большого пальца. и это то, что дизассемблер пытается сделать из этих 32-битных значений, это адреса. person Nixmd; 06.03.2017

  2. Nixmd

    Прежде всего — не думайте слишком много об экономии вспышки. Когда я начинал с микроконтроллеров, у меня был тот же план, что и у вас, но позже пришел к выводу, что это вообще не имеет смысла. В примере микросхемы STM32F4 есть флэш-память, которая гарантирует минимум 10000 циклов записи / стирания. Вам нужно будет программировать доску 14 раз в день, каждый божий день в течение двух лет подряд, чтобы достичь этого значения. И даже после того, как до него дотянешься, не сказано, что вспышка сразу перестает работать. Скорее всего, не стоит рассчитывать на то, что содержимое флэш-памяти сохранится в течение гарантированных 20 лет. Все эти усилия не стоят хлопот, учитывая выносливость и обычные циклы использования (в среднем ваша плата будет выполнять, возможно, несколько циклов записи / стирания в день, и вы, вероятно, не будете играть с ней через несколько лет в любом случае). Особенно если говорить о дешевых платах.

    TL; DR: только не пытайтесь экономить вспышку. Это не стоит всех хлопот.

    Если вы действительно хотите выполнить код из RAM и вообще не записывать во флеш-память, просто помните, что это только возможно с отладчиком. В противном случае вам пришлось бы написать свой код для флэш-памяти с помощью небольшой процедуры, которая скопировала бы его в ОЗУ и затем запустила его оттуда, что было бы совершенно бессмысленно с учетом вашей первоначальной идеи сохранения флэш-памяти. В любом случае — если вы хотите это сделать, это довольно просто, и все, что вам нужно сделать, это изменить скрипт компоновщика. Прежде всего полностью удалите блок памяти «rom» (или, возможно, «flash» или что-то подобное) из раздела MEMORY. Теперь замените все использования удаленной памяти блоком памяти RAM, так что вам, вероятно, следует заменить все вхождения «rom» на «ram» (или, может быть, «flash» на «sram» или что-то подобное). На данном этапе это должно действительно работать. Последнее, что вам нужно сделать, это полностью удалить код и функциональные возможности для выполнения инициализации раздела .data — для этого потребуются изменения сценария компоновщика (убедитесь, что LMA этого раздела идентичен его VMA) и удаление кода инициализации из Reset программа-обработчик.

    Обратите внимание, что для того, чтобы эта процедура работала, вам необходимо:

    • выберите «загрузка из SRAM» с помощью контактов BOOT0 и BOOT1,
    • заставить ПК и ИП исправить адреса с помощью отладчика.

    Для вашей платы Nucleo первый вариант, к сожалению, недоступен, так как контакт BOOT1 (который в данном случае должен быть высоким) закорочен на GND.

    Но опять же — просто не делайте этого, это не стоит того.

    cortex-m использует таблицу векторов, в отличие от полноразмерной руки, поэтому точка входа неверна, отладчик должен будет войти при сбросе или удалить таблицу векторов, в любом случае придется заменить инициализацию указателя стека. person Nixmd; 05.03.2017

    @old_timer — все проблемы, которые вы подняли в своем комментарии, вообще не имеют значения, так как с отладчиком вы можете (и — в этой ситуации — должны!) делать с ядром все, что хотите. Отладчик может настроить компьютер для запуска в любом месте. Он также может настроить указатель стека. А с STM32, если вы хотите запускать код из ОЗУ, вы должны соответствующим образом установить контакты BOOTx, что просто решит все проблемы, о которых вы упомянули. person Nixmd; 05.03.2017

    где вы упомянули булавки буткса? а где они на нуклео плате разбиты? person Nixmd; 06.03.2017

    ваша процедура просто приводит к сбою, как определено, необходимо завершить. person Nixmd; 06.03.2017

    Существуют допустимые варианты использования для работы в ОЗУ, в основном о возможности сохранить содержимое и скорость FLASH (намного быстрее, чем стирание и запись). В настоящее время я занимаюсь этим, и он используется для инициализации и проверки STM32 и периферийных устройств, которые доступны только за ним. Решение требует использования встроенного загрузчика UART STM32 для загрузки прошивки в ОЗУ и ее запуска. Таким образом, вы можете автоматизировать тесты, при условии, что это совсем не то, что нужно @Nixmd. person Nixmd; 06.07.2017

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: