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

Keil uVision. Выполнение кода из RAM

5 hours ago, VladislavS said:

ИМХО, если хочется выполнять рабочий код из SRAM, то самое правильное будет:

- скомпилировать рабочую прошивку с тех адресов, где она штатно будет работать. Так и отлаживать проще.

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

- Написать начальный загрузчик, который копирует прошивку из flash в SRAM, делает remap и передаёт ей управление.

 

Можно, конечно, чтобы загрузчик был частью основной прошивки, но надо ли? Всё равно, при удалённом обновлении неубиваемый загрузчик лучше иметь.

Линкер и штатный иниуиализатор прекрасно всё это делает из коробки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

23 minutes ago, VladislavS said:

Интересно было бы посмотреть.

Так примеры есть под нужный камень.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

18 часов назад, VladislavS сказал:

Интересно было бы посмотреть.

После чтения мануала и некоторых экспериментов, я пришел к варианту, что описан вот тут:smile:

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(), который разместит в ОЗУ всю таблицу векторов и код с данными.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

   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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сейчас сделал вот так у себя

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-файл, вроде все как нужно. Но буду еще проверять по ходу написания прошивки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

Есть вопрос следующего характера. Хочу понять, насколько бредовая мысль, посетившая меня в процессе.
Возможно ли в пределах одного проекта слинковать программу так, чтобы копия одной и той же функции была в разных регионах памяти?
Идея в чем: при запуске, но до вызова __main(), я хочу выполнять копию func(), которая хранится во Flash. После выполнения __main() - копию из RAM.
Т.е. до вызова __main() память в ОЗУ (секции RO/RW/ZI) еще не проинициализирована. Соответственно, func() там еще нет. Но она есть во Flash.
Реально ли добраться до места хранения функции в Load Region и оттуда исполнить? Правда, нужно обеспечить, чтобы функция там была не упакована.

Или так никто не делает? Это нечто похожее на overlay, только в обратную сторону.
Вызывать такую функцию, что то типа func() - для вызова по умолчанию, а как-нибудь func() __attribute__(...) - для вызова копии из другого региона.

Бред?:this:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Бред?:this:

Нет, задача действительно интересная. Присоединяюсь к вопросу. Попахивает динамической линковкой, или как она там кграмотно называется. Запускала же та же DOS  (ссылаюсь на неё с акцентом на время разработки, и возможности линковки) программы в разных регионах памяти))

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

Есть вопрос следующего характера.

Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно?:dance3:

Изменено пользователем MrBearManul

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Реально ли добраться до места хранения функции в Load Region и оттуда исполнить? Правда, нужно обеспечить, чтобы функция там была не упакована.

В IAR в свойствах проекта есть ключик "Position-independence" с подключиком "Code and read-only data (ropi)". По дефолту они сброшены. Что как бы намекает что обычно генерится позиционно-зависимый код. Я не проверял что именно от этого зависит, но можно покопать в ту сторону. Если скомпилить код с этим ключиком, то наверное его можно вызывать откуда угодно.

Кроме упаковки могут быть ещё какие-то подводные камни (на что косвенно намекает ключик описанный выше). Возможно что могут быть какие-то относительные адресации (настраиваемые компоновщиком) чего-то за пределами копируемого load-mage. Относительно содержимого PC по адресу исполнения или относительно адресов const-данных из адреса исполнения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

21 минуту назад, MrBearManul сказал:

Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно?

Делаю загрузчик для одного МК на STM32F0, и хочу, чтобы он выполнялся из ОЗУ.
Также хочу, чтобы вся программа была в пределах одного проекта в Keil.
При сбросе МК из Flash выполняется некоторая backend-логика. Это

  • проверка на target-allowed. В устройстве несколько МК. Если перепутают бинари прошивок, МК запуститься не должен.
  • инициализация периферии для определения критериев запуска загрузчика: их (критериев) несколько.
  • если необходимости оставаться в загрузчике нет - переходим в основное ПО (приложение).
  • если по какой-то причине пришлось остаться в загрузчике, выполняем __main(). Она подготовит окружение и передаст управление в main().

Сама main() будет уже в ОЗУ. И вся логика загрузчика - в ОЗУ. Все нужные мне функции - в ОЗУ. Так мне требуется.
Поэтому тут возникла (не сказать чтобы прям глобальная) проблема - до передачи управления __main() весь backend-код можно выполнить из Flash.
Но суть в том, что, например, функция расчета CRC используется и в логике загрузчика, и в логике backend-кода. Т.е. функция может быть вызвана из RAM и Flash.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

35 минут назад, MrBearManul сказал:

Встречный вопрос, извините если не понял из вашего поста, а зачем вам это нужно?:dance3:

Видимо хочется вызывать RAM-функцию не только из ОЗУ, но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только что, jcxz сказал:

Видимо хочется вызывать RAM-функцию не только из ОЗУ, но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать.

Верно.
Только не то что ее туда нельзя скопировать, скопировать то можно.
Просто копировать нужно будет руками и всякий раз, когда появляется очередная (новая) функция.
А так - __main() все сам куда нужно распакует:smile:
Было бы здорово, если бы прямо в коде можно было задавать, из какого региона осуществлять вызов функции.
Какой-нибудь там прагмой или атрибутом.

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

"Position-independence"

Наверное это было бы как раз тем, что нужно, но в случае, когда эта функция могла бы гулять в пределах ОЗУ.
А у меня она после инициализации __main() прибита гвоздями в ОЗУ и ее адрес не поменяется. Но ведь копия во Flash-то есть! Вот ее и хочу вызвать:wink:

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Наверное это было бы как раз тем, что нужно, но в случае, когда эта функция могла бы гулять в пределах ОЗУ.

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

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

Просто копировать нужно будет руками и всякий раз, когда появляется очередная (новая) функция.

Ну и что? В чём проблема скопировать руками и выполнить? Или выполнить то, что скопировано до запуска main() стартап-кодом?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

При сбросе МК из Flash выполняется некоторая backend-логика.

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

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

но из флеша, когда её место в ОЗУ занято чем-то другим и нельзя её туда скопировать.

Гм. Это понятно) Но скажем так, весьма необычно. Поэтому я и уточнил.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...