Как я могу выполнить функцию от RAM на Cortex-M3 (STM32)?

StackOverflow https://stackoverflow.com/questions/3044010

  •  27-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь выполнить функцию от RAM на процессоре Cortex-M3 (STM32). Функция стирает и переписывает внутреннюю вспышку, поэтому мне определенно нужно быть в RAM, но как мне это сделать?

То, что я попробовал, это: скопируйте функцию в байтовый массив в оперативной памяти, используя memcpy (проверка того, что он правильно выровнен), установив указатель функции, чтобы указать на массив байта, а затем вызова функции (указатель).

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

В любом случае, есть правильный способ сделать это? Как будет выглядеть файл Scatter, который автоматически размещает функцию в оперативной памяти (я использую keil uvision для Cortex-M3)?

Редактировать: Подробнее: Насущная информация: RealView MDK-ARM V 4.10 Компилятор: ARMCC V4.0.0.728 Ассемблер: Armasm V4.0.0.728 Синкер: Armlink V4.0.0.728 Процессор: STM32F103ZE

Бит ImpreciserRERT устанавливается в регистре неисправностей шины, когда произойдет сброс.

Это было полезно?

Решение

Квабру при итерации петли, вероятно, потому что функция ветвивается до абсолютного адреса и не относится к новой функции в памяти в ОЗУ. Получите бы доступ к исходному расположению кода в точке привести к ошибке шины из-за операции Flash Erase?

Я верю, что вы можете отметить функцию, которая будет сознаваться и правильно скопирована на RAM с CARM, добавив __ram Директива к определению функции. Для обучения о том, как сделать то же самое с компилятором RealView см. Выполнение функций в оперативной памяти Артикул технической поддержки:

μVision позволяет найти модули к определенным областям памяти, которые вводятся в диалоговом окне Проект - Опции - цель. Отказ Чтобы сделать это, щелкните правой кнопкой мыши на исходном файле (или группе файлов) и откройте диалог Опции - Свойства. Отказ Затем выберите регионы памяти под Назначение памяти.

Есть пример в папке ArmexampleRam_function.

Это должно генерировать код запуска, чтобы позаботиться о копировании функции в RAM и правильно связывание вызовов на это место. В противном случае, если вам нужно динамически копировать произвольные функции в RAM, затем посмотрите в компиляцию Независимый код позиции (PIC) С ReallView.

Другие советы

Не зная больше о вашей ситуации, я могу предложить только несколько общих вещей ... Убедитесь, что у вас есть действительный стек для этой функции (или избегайте всех операций стека в функции), что ваши прерывания отключены, и что любые векторы в Системная векторная таблица не указывает на код, который уходит, когда вы стерете вспышку. Наконец, убедитесь, что ваша функция связанный Чтобы запустить по адресу, вы положите его ... Код не может быть перемонтирован и может прыгать в точку в старом месте.

Поскольку ARM имеет ограниченную возможность загружать немедленные данные, утилиты, которые генерируют код для ARM, часто скрывающий код и данные. Например, заявление, как

void myRoutine(void)
{
  myVar1=0x12345678;
  myVar2=0x87654321;
}

может закончиться как что-то вроде:

myRoutine:        
    ldr r0,=myVar1; Load the address of _myVar
    ldr r1,=0x12345678
    str r1,[r0]
    ldr r0,=myVar1; Load the address of _myVar
    ldr r1,=0x87654321
    str r1,[r0]
    bx  lr

which would get translated into:
    ldr r0,dat1
    ldr r1,dat2
    str r1,[r0]
    ldr r0,dat3
    ldr r1,dat4
    str r1,[r0]
    bx  lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678

or perhaps even something like:
    mar  r0,dat1
    ldrm r0,[r1,r2,r3,r4]
    str r2,[r1]
    str r4,[r3]
    bx  lr
... followed some time later by
dat1 dcd _myVar1
dat2 dcd 0x12345678
dat3 dcd _myVar2
dat4 dcd 0x12345678

Обратите внимание, что _myvar и 0x12345678 могут быть размещены сразу после кода для рутины, в котором они появляются; Если вы попытаетесь определить длину процедуры, используя метку, которая следует за последней инструкцией, такая длина не будет включать дополнительные данные.

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

Моя рекомендация будет написать небольшую рутину на языке сборки, чтобы делать то, что вам нужно. Это всего лишь несколько инструкций, вы можете точно знать, какой код делает код и какие адресные зависимости он мог иметь, и вам не придется беспокоиться о будущих версиях компилятора, изменяющих свой код таким образом, чтобы сломать что-то [например, третий Версия вышеуказанного кода не будет проблем, даже если dat1 Приземлился на нечетном полусловеческом границе, поскольку инструкция M3 LDR может обрабатывать ненужные чтения, но четвертая (слегка быстрее и более компактная) версия с использованием LDRM будет выполнен в таком случае; Даже если сегодняшняя версия компилятора использует четыре инструкции LDR, будущая версия может использовать LDRM].

С помощью Compiler IAR (я знаю, что ваш вопрос: keil, но у меня нет его, чтобы играть) Вы можете пометить либо весь проект, либо отдельный файл, чтобы быть «независимым положением». От использования этого в прошлом с другими процессорами, это означает, что вы можете переместить его «где угодно», и он все еще будет работать хорошо

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top