|
Эмуляция EEPROM в первых двух секторах STM32F4, Старт программы с предопределённого адреса |
|
|
|
Aug 28 2013, 04:48
|

Участник

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731

|
Всем добрый день. Для камня STM32F407 взял эмулятор EEPROM с сайта st. Вложил в свой проект с оригинальными настройками как в примере. Всё вроде как работает нормально. Но там EEPROM эмулируется во втором и третьем секторах FLASH памяти (которые по 16к). Я в своём проекте перенёс эмуляцию EEPROM в первые два сектора и соответственно сдвинул таблицу векторов прерывания на второй сектор: Код define symbol __ICFEDIT_intvec_start__ = 0x08008000; (в stm32f4xx_flash.icf) #define VECT_TAB_OFFSET 0x8000 (в system_stm32f4xx.c) Необходимые изменения внёс в eeprom.h. В своём проекте в начале вставил пример записи трёх переменных в память. Всё как бы работает, НО только с отладчиком из IAR контроллер стартует как надо. Если сделать сброс кнопкой, то уже не стартует. Я пока перенёс эмуляцию EEPROM в последние два сектора, но они по 128к и откусывать пол флеша как-то не охота. В такой конфигурации всё работает как надо. Чувствую, что надо указать в прерывании сброса откуда стартовать программе. Помогите разобраться с проблемкой. Спасибо.
--------------------
Александр, UT4UBL
|
|
|
|
|
Aug 28 2013, 05:40
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
QUOTE (AlexUT4 @ Aug 28 2013, 06:48)  Чувствую, что надо указать в прерывании сброса откуда стартовать программе. Программа стартует с адреса, указанного в векторе по адресу 4. Из адреса 0 берется начальное значение указателя стека. Эти адреса прибиты гвоздями. Переносите свою EEPROM в последние сектора. В первом (нулевом) должна находиться таблица прерываний.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 28 2013, 08:04
|

Участник

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731

|
Цитата(Сергей Борщ @ Aug 28 2013, 08:40)  Программа стартует с адреса, указанного в векторе по адресу 4. Из адреса 0 берется начальное значение указателя стека. Эти адреса прибиты гвоздями. Переносите свою EEPROM в последние сектора. В первом (нулевом) должна находиться таблица прерываний. Про таблицу векторов понял. Тогда в нулевом секторе надо разместить начало таблицы прерываний. В прерывании сброса сделать переход на начало программы расположенной после Sector 1 и Sector 2, которые заняты под EEPROM. То есть основную программу расположить, начиная с Sector 3. Я правильно мыслю? Цитата(scifi @ Aug 28 2013, 10:02)  Как уже сказано, первый сектор занять для эмуляции EEPROM не получится. А чем не устраивают второй и третий секторы? Вы имели ввиду Sector 2 Sector 3 или Sector 1 Sector 2 ? В примере эмуляция сделана в Sector 2 и Sector 3, а основной код закладывается с самого начала FLASH и, как я думаю, есть опасность перекрытия кода программы с секторами EEPROM. В линковщике я никаких мер по избеганию наложения не увидел (может плохо смотрел).
--------------------
Александр, UT4UBL
|
|
|
|
|
Aug 28 2013, 09:26
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(AlexUT4 @ Aug 28 2013, 12:04)  есть опасность перекрытия кода программы с секторами EEPROM вариантов месколько. Можно линковщику сказать, что флеш располагается тут и тут, а еепром-сектора обойти также при эмуляции eeprom можно на получившийся адрес накладывать маску, которая позволит не "выпрыгнуть" за диапазон отведенных секторов Цитата(Сергей Борщ @ Aug 28 2013, 13:18)  Тогда вам достаточно будет в скрипте линкера уменьшить доступный программе объем флеша. и loadregion разбивать не придется. Честно говоря, даже и не пробовал никогда собирать с "дырками" хотя... эту область также можно в loadregion включить и получится без разрывов, только код в ней не размещать
|
|
|
|
|
Aug 28 2013, 09:45
|

Участник

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731

|
Цитата(Сергей Борщ @ Aug 28 2013, 12:18)  В целом - да. Фактически в нулевом секторе вам надо расположить два первых элемента таблицы (указатель стека и адрес вектора сброса). А в основной программе все равно надо будет иметь полную таблицу векторов и в процессе запуска программы записать ее адрес в регистр VTOR. Но ради чего все это городить? Почему не выделить под EEPROM последние сектора? Тогда вам достаточно будет в скрипте линкера уменьшить доступный программе объем флеша. Два последних сектора по 128к. А это половина памяти МК. Не выгодно. Первые четыре сектора по 16к. Цитата(toweroff @ Aug 28 2013, 12:26)  вариантов месколько. Можно линковщику сказать, что флеш располагается тут и тут, а еепром-сектора обойти
также при эмуляции eeprom можно на получившийся адрес накладывать маску, которая позволит не "выпрыгнуть" за диапазон отведенных секторов
и loadregion разбивать не придется. Честно говоря, даже и не пробовал никогда собирать с "дырками"
хотя... эту область также можно в loadregion включить и получится без разрывов, только код в ней не размещать Я сейчас линковщику указал что доступная память начиная с 0x0800C000 это Sector 3. Код define symbol __ICFEDIT_region_ROM_start__ = 0x0800C000 Вектора по умолчанию в начало флеша. В настройках эмулятора EEPROM Код #define EEPROM_START_ADDRESS ((uint32_t)0x08004000) это Sector 1. В памяти основной код лёг с 0x0800C000. Основная таблица прерываний легла с 0x08000000. По адресу 4 указатель на вектор прерывания, который расположен выше 0x0800C000. А там дальше SystemInit и стар основной программы. Пока всё завелось и работает. Тестирую…. Но как-то не выгодно с этими секторами – получается, что первый сектор в 16к «гуляет почти свободным». Там сейчас всего не более 512 байт записано. Не рационально)))) Как указать линковщику, что бы он ничего не располагал с адреса 0x08004000 по 0x0800BFFF ? Тогда память будет выгоднее использоваться.
--------------------
Александр, UT4UBL
|
|
|
|
|
Aug 28 2013, 19:40
|

Участник

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731

|
Цитата(scifi @ Aug 28 2013, 14:48)  В "старом" яровском линкере (XLINK) можно было сказать линкеру, чтобы размещал в разных кусках памяти, типа так: -Z(CODE)CODE=0x08000000-0x08003FFF, 0x0800C000-0x0807FFFF. И ведь реально работало. В "новом" линкере (ILINK) я не разбирался, но думаю, что он тоже это умеет (заглядывал в мануал). Попробуйте подправить файл конфигурации линкера: define region ROM_region = mem:[from 0x08000000 to 0x08003FFF] mem:[from 0x0800C000 to 0x0807FFFF]; Большое спасибо за наводку. Почитал доку на линковщик. Там много чего можно сделать, в том числе и регион с дырой. Я переделал так stm32f4xx_flash.icf : Код .......... define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF; define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; define symbol __ICFEDIT_region_RAM_end__ = 0x2001FFFF; define symbol __ICFEDIT_region_CCMRAM_start__ = 0x10000000; define symbol __ICFEDIT_region_CCMRAM_end__ = 0x1000FFFF;
define symbol __EEPROM_region_ROM_start__ = 0x08004000; /* Начало и конец памяти под эмуляцию EEPROM */ define symbol __EEPROM_region_ROM_end__ = 0x0800BFFF;
/*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0x800; define symbol __ICFEDIT_size_heap__ = 0x400; /**** End of ICF editor section. ###ICF###*/
define memory mem with size = 4G; define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to (__EEPROM_region_ROM_start__ - 0x00000001)] | mem:[from (__EEPROM_region_ROM_end__ + 0x00000001) to __ICFEDIT_region_ROM_end__]; .......... Полёт нормальный. Но только в Sector 0 линковщик совсем немного кода добавил. Всё остальное уже после выделенной EEPROM памяти. Всем спасибо за ликбезы))))
--------------------
Александр, UT4UBL
|
|
|
|
|
Aug 29 2013, 07:20
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(AlexUT4 @ Aug 28 2013, 23:40)  Но только в Sector 0 линковщик совсем немного кода добавил. Всё остальное уже после выделенной EEPROM памяти. Наверное, это потому, что весь программный код складывается в одну большую сплошную секцию. Соответственно, в нулевой сектор попадают оставшиеся крохи: таблица векторов прерываний, константы, начальные значения статических переменных. Можете проверить это предположение, заглянув в MAP файл. Помню, что GCC умеет выделять отдельную секцию для каждой функции, а вот йар - не похоже...
|
|
|
|
|
Aug 29 2013, 08:16
|

Участник

Группа: Участник
Сообщений: 15
Регистрация: 2-05-11
Пользователь №: 64 731

|
Цитата(scifi @ Aug 29 2013, 10:20)  Наверное, это потому, что весь программный код складывается в одну большую сплошную секцию. Соответственно, в нулевой сектор попадают оставшиеся крохи: таблица векторов прерываний, константы, начальные значения статических переменных. Можете проверить это предположение, заглянув в MAP файл. Помню, что GCC умеет выделять отдельную секцию для каждой функции, а вот йар - не похоже... Да, разложил линковщик так: ******************************************************************************* *** PLACEMENT SUMMARY *** "A1": place at 0x08000000 { ro section .intvec }; "P1": place in [from 0x08000000 to 0x08003fff] | [from 0x0800c000 to 0x0807ffff] { ro }; "P2": place in [from 0x20000000 to 0x2001ffff] { rw, block CSTACK, block HEAP }; Section Kind Address Size Object ------- ---- ------- ---- ------ "A1": 0x188 .intvec ro code 0x08000000 0x188 startup_stm32f40xx.o [1] - 0x08000188 0x188 "P1", part 1 of 2: 0x250 .rodata const 0x08000188 0x0 zero_init3.o [5] .rodata const 0x08000188 0x0 lz77_init.o [5] Initializer bytes ro data 0x08000188 0x24f <for P2 s0> - 0x080003d7 0x24f "P1", part 2 of 2: 0x10cdc .text ro code 0x0800c000 0x2060 shell.o [1] .text ro code 0x0800e060 0x1bc ip_addr.o [1] .text ro code 0x0800e21c 0xc errno.o [3] .text ro code 0x0800e228 0x110 xstrerro.o [3] .text ro code 0x0800e338 0x36 strlen.o [5] .text ro code 0x0800e36e 0x22 zero_init3.o [5] .text ro code 0x0800e390 0x3f4 api_lib.o [1] ..... будет место для констант и инициализаций. Их планируется не мало.
--------------------
Александр, UT4UBL
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|