24190

Расположение функций в ОЗУ, программирование EEPROM

Дата последнего изменения: 24.11.2020 18:09:50

Отключение прерываний

Так как нельзя одновременно писать в Flash-память и исполнять из нее команды, при программировании Flash-памяти необходимо, чтобы программа выполнялась из ОЗУ. Flash-память переключается в режим программирования и, если происходит обращение на чтение, то процессор попадает в HardFault.

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

__set_PRIMASK(1); // Отключение всех прерываний кроме NMA и HardFault
 или
__set_FAULTMASK(1); // Отключение всех прерываний кроме NMA

Подробнее в статье Прерывания и приоритеты

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

Пример работы с EEPROM

Работу с EERPOM рассмотрим на примере Sector_Operations для МК 1986ВЕ92. После установки Software pack для Keil MDK 5 (https://ic.milandr.ru/soft/) этот пример расположен по пути:

C:\Keil_v5\Arm\Packs\Keil\MDR1986BExx\1.5.3\Examples\MDR1986VE9x\MDR32F9Q2_EVAL\EEPROM\Sector_Operations

Создаем новый проект, как описано в статье Создаем новый проект. В качестве устройства (device) нужно выбирать МК 1986ВЕ92. При создании проекта подключаем разделы библиотеки - Startup_MDR32F9Qx, EEPROM, PORT, RST_CLK. В проект добавляем файл main.c из указанного выше пути. В статье Создаем новый проект был создан новый файл main.c, здесь же проще кликнуть правой клавишей мыши на папке user и выбрать "Add Existing File …" . Затем нужно скомпилировать проект, загрузить проект в память микроконтроллера и выполнить действия, описанные ниже (см. рисунок 1):

  1. Включить режим отладки.
  2. Поставить точку останова на первой функции обращения к EEPROM.
  3. Запустить F5 или кнопкой в тулбаре.
  4. Остановиться перед входом в выбранную функцию. При этом можно увидеть, что код находится в адресах Flash-памяти.

 Рисунок 1

Теперь необходимо зайти внутрь функции EEPROM_ErasePage (рисунок 2).

  1. Нажать F11 или используем кнопку в тулбаре.
  2. Указатель команд находится в начале функции.
  3. Функция находится в адресах Flash памяти.

 Рисунок 2

Получается, что пример, запущенный по умолчанию, не располагает функции работы с EEPROM в области памяти ОЗУ. Такой код при исполнении будет приводить к HardFault. Если осуществить дальнейший запуск программы, то будет видно, что исполнение никогда не выйдет из функции EEPROM_ErasePage.

Располагаем файл "MDR32F9Qx_eeprom.c" в ОЗУ

Для того чтобы расположить весь библиотечный файл работы с EEPROM в ОЗУ, нужно при клике правой клавишей мыши на файле выбрать "Options for Component …" (рисунок 3).

 Рисунок 3

В открывшемся окне в закладке Memory необходимо выбирать расположение Code в доступных областях памяти (рисунок 4).

 Рисунок 4

Доступные области памяти определены в окне Options проекта (рисунок 5). Здесь нужно выбрать только область ОЗУ - IRAM1 (Internal RAM1).

 Рисунок 5

При размещении исполняемого кода в ОЗУ для МК 1986ВЕ1Т необходимо выбирать память IRAM2, адреса которой начинаются с 0x20100000. Только к этой памяти имеет доступ шина AHB_Lite, поэтому код из этой памяти может исполняться. Этот же диапазон следует выбирать для данных при работе с DMA.

ВАЖНО также выставить опцию - "Use Memory Layout from Target Dialog" в закладке Linker опций проекта. Без этого код файла MDR32F9Qx_eeprom.c не окажется в диапазонах памяти ОЗУ (рисунок 6).

 Рисунок 6

После этого нужно снова скомпилировать проект, загрузить в кристалл и в режиме отладки зайти внутрь функции EEPROM_ErasePage. Теперь в окне ассемблера видно, что функция находится в адресах ОЗУ (рисунок 7).

 Рисунок 7

Если запустить проект, то он отработает успешно.

Располагаем отдельные функции в памяти

Существует еще один вариант, как можно разместить функции в памяти ОЗУ. Для того, чтобы воспользоваться вторым вариантом, нужно вернуть проект в исходное состояние. Если посмотреть определение функции EEPROM_ErasePage в "MDR32F9Qx_eeprom.h", то видно, что она определена с некоторыми атрибутами:

__RAMFUNC void EEPROM_ErasePage(uint32_t Address, uint32_t BankSelector) __attribute__((section("EXECUTABLE_MEMORY_SECTION")));

Атрибут __RAMFUNC не воспринимается Keil.

Запись __attribute__((section("EXECUTABLE_MEMORY_SECTION"))) воспринимается Keil так, что он пытается разместить эту функцию в секцию памяти с именем EXECUTABLE_MEMORY_SECTION. Для того чтобы использовать этот атрибут, необходимо внести исправления с скаттер-файл (scatter-file).

 Рисунок 8

При включении опции «Use Memory Layout from Target Dialog» создается файл *.sct по умолчанию. При каждой компиляции этот файл будет обновляться. Для того чтобы этого не происходило, нужно выключить опцию «Use Memory Layout from Target Dialog». Далее необходимо найти скаттер-файл в папке проекта и открыть его блокнотом. Ниже представлен его листинг по умолчанию:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

 LR_IROM1 0x20000000 0x00001000 { ; load region size_region
  ER_IROM1 0x20000000 0x00001000 { ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
    .ANY (+RO)
  }
  RW_IRAM1 0x20001000 0x00001000 { ; RW data
 .ANY (+RW +ZI)
  }
}

Здесь определены две области памяти - Flash и ОЗУ. Необходимо добавить запись, чтобы данные, помеченные атрибутом EXECUTABLE_MEMORY_SECTION из всех объектных файлов, располагались в адресах ОЗУ. Сделать это можно следующим образом:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x20000000 0x00001000 { ; load region size_region
  ER_IROM1 0x20000000 0x00001000 { ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   }
  RW_IRAM1 0x20001000 0x00001000 { ; RW data
  *.o (EXECUTABLE_MEMORY_SECTION)
   .ANY (+RW +ZI)
   }
 }

Более подробно про скаттер-файл можно прочитать в описании Keil

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

Первый способ - расположение всего файла в ОЗУ - более прост и, поскольку в файле MDR32F9Qx_eeprom.c сосредоточена только работа с EEPROM, этот способ получил большее распространение.

Функция стирания по секторам стирает заданный сектор в указанном банке - в информационном или основном. НО функция стирания микросхемы целиком, при выборе информационного банка стирает основную память тоже!

EEPROM_EraseAllPages(EEPROM_Info_Bank_Select); // Стирает основную память и информационную

Сохранить статью в PDF

Программное обеспечение

Standard Peripherals Library + software pack для Keil MDK 5
Standard Peripherals Library + software pack для Keil MDK 5
ОФИЦИАЛЬНАЯ СБОРКА
Standard Peripherals Library – библиотека для микроконтроллеров.

Теги

Была ли статья полезной?