x893 61 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 5 hours ago, VladislavS said: ИМХО, если хочется выполнять рабочий код из SRAM, то самое правильное будет: - скомпилировать рабочую прошивку с тех адресов, где она штатно будет работать. Так и отлаживать проще. - прошить её во Flash с некоторым смещением, чтобы вначале поместился начальный загрузчик. - Написать начальный загрузчик, который копирует прошивку из flash в SRAM, делает remap и передаёт ей управление. Можно, конечно, чтобы загрузчик был частью основной прошивки, но надо ли? Всё равно, при удалённом обновлении неубиваемый загрузчик лучше иметь. Линкер и штатный иниуиализатор прекрасно всё это делает из коробки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба Интересно было бы посмотреть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 61 11 декабря, 2020 Опубликовано 11 декабря, 2020 · Жалоба 23 minutes ago, VladislavS said: Интересно было бы посмотреть. Так примеры есть под нужный камень. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
VladislavS 39 12 декабря, 2020 Опубликовано 12 декабря, 2020 · Жалоба Не обижусь, если ткнёте носом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 12 декабря, 2020 Опубликовано 12 декабря, 2020 · Жалоба 18 часов назад, VladislavS сказал: Интересно было бы посмотреть. После чтения мануала и некоторых экспериментов, я пришел к варианту, что описан вот тут ROM_LOAD 0x0000 0x4000 { ROM_EXEC 0x0000 0x4000 ; root region at 0x0 { vectors.o (Vect, +FIRST) ; Vector table * (InRoot$$Sections) ; All library sections that must be in a ; root region, for example, __main.o, ; __scatter*.o, __dc*.o, and * Region$$Table } RAM 0x10000 0x8000 { * (+RO, +RW, +ZI) ; all other sections } } Ну немного только доработать. В корневой регион поместить не все вектора, а лишь верхушку стека и вектор сброса. В векторе сброса осуществить вызов _main(), который разместит в ОЗУ всю таблицу векторов и код с данными. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 61 12 декабря, 2020 Опубликовано 12 декабря, 2020 · Жалоба RAM functions are defined using the toolchain options. Functions that are executed in RAM should reside in a separate source module. Using the 'Options for File' dialog you can simply change the 'Code / Const' area of a module to a memory space in physical RAM. Available memory areas are declared in the 'Target' tab of the 'Options for Target' dialog. Код в RAM скопируется при инициализации памяти. Делать руками не надо ничего. https://community.nxp.com/t5/LPCXpresso-IDE-FAQs/Relocating-code-from-FLASH-to-RAM/m-p/473993 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 12 декабря, 2020 Опубликовано 12 декабря, 2020 · Жалоба Сейчас сделал вот так у себя LOADREG 0x08000000 8192 { ROOTREG 0x08000000 8192 { *(InRoot$$Sections) startup.o (RSTDATA, +First) startup.o (RSTCODE) hw.o (romfunc) } RAMREG 0x20000000 8192 { startup.o (VTBL, +First) .ANY (+RO +RW +ZI) } } Стартап взял из стандартных и подправил под себя Скрытый текст ; STM32F030 Stack_Size EQU 0x00000400 Heap_Size EQU 0x00000000 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit PRESERVE8 THUMB AREA RSTDATA, DATA, READONLY DCD __initial_sp DCD Reset_Handler AREA RSTCODE, CODE, READONLY Reset_Handler PROC EXPORT Reset_Handler IMPORT hw_SysClkInit IMPORT __main LDR R0, =hw_SysClkInit BLX R0 LDR R0, =__main BX R0 ENDP AREA VTBL, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler DCD WWDG_IRQHandler ; Window Watchdog DCD 0 ; Reserved DCD RTC_IRQHandler ; RTC through EXTI Line DCD FLASH_IRQHandler ; FLASH DCD RCC_IRQHandler ; RCC DCD EXTI0_1_IRQHandler ; EXTI Line 0 and 1 DCD EXTI2_3_IRQHandler ; EXTI Line 2 and 3 DCD EXTI4_15_IRQHandler ; EXTI Line 4 to 15 DCD 0 ; Reserved DCD DMA1_Channel1_IRQHandler ; DMA1 Channel 1 DCD DMA1_Channel2_3_IRQHandler ; DMA1 Channel 2 and Channel 3 DCD DMA1_Channel4_5_IRQHandler ; DMA1 Channel 4 and Channel 5 DCD ADC1_IRQHandler ; ADC1 DCD TIM1_BRK_UP_TRG_COM_IRQHandler ; TIM1 Break, Update, Trigger and Commutation DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD 0 ; Reserved DCD TIM3_IRQHandler ; TIM3 DCD 0 ; Reserved DCD 0 ; Reserved DCD TIM14_IRQHandler ; TIM14 DCD 0 ; Reserved DCD TIM16_IRQHandler ; TIM16 DCD TIM17_IRQHandler ; TIM17 DCD I2C1_IRQHandler ; I2C1 DCD 0 ; Reserved DCD SPI1_IRQHandler ; SPI1 DCD 0 ; Reserved DCD USART1_IRQHandler ; USART1 __Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors AREA |.text|, CODE, READONLY NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDP SVC_Handler PROC EXPORT SVC_Handler [WEAK] B . ENDP PendSV_Handler PROC EXPORT PendSV_Handler [WEAK] B . ENDP SysTick_Handler PROC EXPORT SysTick_Handler [WEAK] B . ENDP Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK] EXPORT RTC_IRQHandler [WEAK] EXPORT FLASH_IRQHandler [WEAK] EXPORT RCC_IRQHandler [WEAK] EXPORT EXTI0_1_IRQHandler [WEAK] EXPORT EXTI2_3_IRQHandler [WEAK] EXPORT EXTI4_15_IRQHandler [WEAK] EXPORT DMA1_Channel1_IRQHandler [WEAK] EXPORT DMA1_Channel2_3_IRQHandler [WEAK] EXPORT DMA1_Channel4_5_IRQHandler [WEAK] EXPORT ADC1_IRQHandler [WEAK] EXPORT TIM1_BRK_UP_TRG_COM_IRQHandler [WEAK] EXPORT TIM1_CC_IRQHandler [WEAK] EXPORT TIM3_IRQHandler [WEAK] EXPORT TIM14_IRQHandler [WEAK] EXPORT TIM16_IRQHandler [WEAK] EXPORT TIM17_IRQHandler [WEAK] EXPORT I2C1_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK] WWDG_IRQHandler RTC_IRQHandler FLASH_IRQHandler RCC_IRQHandler EXTI0_1_IRQHandler EXTI2_3_IRQHandler EXTI4_15_IRQHandler DMA1_Channel1_IRQHandler DMA1_Channel2_3_IRQHandler DMA1_Channel4_5_IRQHandler ADC1_IRQHandler TIM1_BRK_UP_TRG_COM_IRQHandler TIM1_CC_IRQHandler TIM3_IRQHandler TIM14_IRQHandler TIM16_IRQHandler TIM17_IRQHandler I2C1_IRQHandler SPI1_IRQHandler USART1_IRQHandler B . ENDP ALIGN IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ALIGN ENDIF END Таким образом я расположил начальный загрузчик во Flash, который при сбросе МК копирует нужный код в ОЗУ. При этом есть возможность располагать некоторые функции во Flash (ну, например, которые вызываются один раз при старте). При определении такой функции надо дописать к ней атрибут размещения в секции romfunc. Например, hw_SysClkInit() будет во Flash __attribute__((section("romfunc"))) void hw_SysClkInit(void) { ... } Посмотрел в map-файл, вроде все как нужно. Но буду еще проверять по ходу написания прошивки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба Приветствую! Есть вопрос следующего характера. Хочу понять, насколько бредовая мысль, посетившая меня в процессе. Возможно ли в пределах одного проекта слинковать программу так, чтобы копия одной и той же функции была в разных регионах памяти? Идея в чем: при запуске, но до вызова __main(), я хочу выполнять копию func(), которая хранится во Flash. После выполнения __main() - копию из RAM. Т.е. до вызова __main() память в ОЗУ (секции RO/RW/ZI) еще не проинициализирована. Соответственно, func() там еще нет. Но она есть во Flash. Реально ли добраться до места хранения функции в Load Region и оттуда исполнить? Правда, нужно обеспечить, чтобы функция там была не упакована. Или так никто не делает? Это нечто похожее на overlay, только в обратную сторону. Вызывать такую функцию, что то типа func() - для вызова по умолчанию, а как-нибудь func() __attribute__(...) - для вызова копии из другого региона. Бред? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 15 декабря, 2020 Опубликовано 15 декабря, 2020 (изменено) · Жалоба 24 минуты назад, Arlleex сказал: Бред? Нет, задача действительно интересная. Присоединяюсь к вопросу. Попахивает динамической линковкой, или как она там кграмотно называется. Запускала же та же DOS (ссылаюсь на неё с акцентом на время разработки, и возможности линковки) программы в разных регионах памяти)) 24 минуты назад, Arlleex сказал: Есть вопрос следующего характера. Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно? Изменено 15 декабря, 2020 пользователем MrBearManul Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба 37 минут назад, Arlleex сказал: Реально ли добраться до места хранения функции в Load Region и оттуда исполнить? Правда, нужно обеспечить, чтобы функция там была не упакована. В IAR в свойствах проекта есть ключик "Position-independence" с подключиком "Code and read-only data (ropi)". По дефолту они сброшены. Что как бы намекает что обычно генерится позиционно-зависимый код. Я не проверял что именно от этого зависит, но можно покопать в ту сторону. Если скомпилить код с этим ключиком, то наверное его можно вызывать откуда угодно. Кроме упаковки могут быть ещё какие-то подводные камни (на что косвенно намекает ключик описанный выше). Возможно что могут быть какие-то относительные адресации (настраиваемые компоновщиком) чего-то за пределами копируемого load-mage. Относительно содержимого PC по адресу исполнения или относительно адресов const-данных из адреса исполнения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба 21 минуту назад, MrBearManul сказал: Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно? Делаю загрузчик для одного МК на STM32F0, и хочу, чтобы он выполнялся из ОЗУ. Также хочу, чтобы вся программа была в пределах одного проекта в Keil. При сбросе МК из Flash выполняется некоторая backend-логика. Это проверка на target-allowed. В устройстве несколько МК. Если перепутают бинари прошивок, МК запуститься не должен. инициализация периферии для определения критериев запуска загрузчика: их (критериев) несколько. если необходимости оставаться в загрузчике нет - переходим в основное ПО (приложение). если по какой-то причине пришлось остаться в загрузчике, выполняем __main(). Она подготовит окружение и передаст управление в main(). Сама main() будет уже в ОЗУ. И вся логика загрузчика - в ОЗУ. Все нужные мне функции - в ОЗУ. Так мне требуется. Поэтому тут возникла (не сказать чтобы прям глобальная) проблема - до передачи управления __main() весь backend-код можно выполнить из Flash. Но суть в том, что, например, функция расчета CRC используется и в логике загрузчика, и в логике backend-кода. Т.е. функция может быть вызвана из RAM и Flash. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба 35 минут назад, MrBearManul сказал: Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно? Видимо хочется вызывать RAM-функцию не только из ОЗУ, но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба Только что, jcxz сказал: Видимо хочется вызывать RAM-функцию не только из ОЗУ, но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать. Верно. Только не то что ее туда нельзя скопировать, скопировать то можно. Просто копировать нужно будет руками и всякий раз, когда появляется очередная (новая) функция. А так - __main() все сам куда нужно распакует Было бы здорово, если бы прямо в коде можно было задавать, из какого региона осуществлять вызов функции. Какой-нибудь там прагмой или атрибутом. 6 минут назад, jcxz сказал: "Position-independence" Наверное это было бы как раз тем, что нужно, но в случае, когда эта функция могла бы гулять в пределах ОЗУ. А у меня она после инициализации __main() прибита гвоздями в ОЗУ и ее адрес не поменяется. Но ведь копия во Flash-то есть! Вот ее и хочу вызвать Тут просто, скорее, спортивный интерес - свою задачу я решил, правда чуть-чуть не так как хотел. И данный вопрос факультативно мог бы помочь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 245 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба 26 минут назад, Arlleex сказал: Наверное это было бы как раз тем, что нужно, но в случае, когда эта функция могла бы гулять в пределах ОЗУ. Не только ОЗУ, а по всей памяти. А значит и её загружаемый образ во флешь должен быть вызываемым (если не сжат каким-либо образом, а тут тоже всё неоднозначно). 26 минут назад, Arlleex сказал: Просто копировать нужно будет руками и всякий раз, когда появляется очередная (новая) функция. Ну и что? В чём проблема скопировать руками и выполнить? Или выполнить то, что скопировано до запуска main() стартап-кодом? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrBearManul 0 15 декабря, 2020 Опубликовано 15 декабря, 2020 · Жалоба 50 минут назад, Arlleex сказал: При сбросе МК из Flash выполняется некоторая backend-логика. Правильно ли я понимаю, что ваш вопрос больше "спортивный", т.е. расчитанный на повышение квалификации или исследование нового? Ведь можно же сразу в стартап-коде скопировать всё ПО в ОЗУ и там выполнить, в т.ч. и backend-логику? Единственный минус, который я вижу - это постоянная задержка на копирование в ОЗУ того, что может быть и не понадобится выполнять в случае старта основного приложение. И того: задержка при каждом запуске прибора. Возможно незначительная. 52 минуты назад, jcxz сказал: но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать. Гм. Это понятно) Но скажем так, весьма необычно. Поэтому я и уточнил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться