Easyelectronics.ru

Электроника для всех
Текущее время: 22 янв 2021, 12:19

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 34 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 15:33 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Доброго времени суток, товарищи.
Пишу на IAR под STM32F103 программку, которая загружает в ОЗУ код и передает ему управление. И всё было прекрасно, пока я использовал для тестов одну и ту же программу в оперативе. Отладил загрузку и сохранение во внешнюю SPI NOR, но потом я сменил тестовую программу на что-то типа
Код:
void test(void){
asm("nop");
}

и в моей жизни появились виниры. С такой фигнёй сталкивался на условных переходах x86, так как они не могли далеко забросить. Тут, оказывается, такое же. Куча ссылок на используемые функции во Flash из функции в SRAM. В коде выше их, понятное дело, нет. Так как они в начале используемого куска памяти, от их количества зависит адрес входа в функцию(((
Так вот в оперативе эти виниры - еще пол-беды, можно и ручками править в заголовке программы все эти адреса, а вот ссылка на эту __ramfunc во флеше (на скрине по адресу 0x8000124 Entry Point для функции в раме) также меняется в зависимости от точки входа. Кто-нибудь делал? Может быть я всё не так делаю?


Вложения:
Безымянный.png
Безымянный.png [ 2.83 Кб | Просмотров: 857 ]
Безымянный.png
Безымянный.png [ 6.89 Кб | Просмотров: 857 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 17:15 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
Вроде на русском написано, но ни хрена не понятно. Так RAM-функции вызываются. В чём проблема то?
Вложение:
v1.png
v1.png [ 47.7 Кб | Просмотров: 831 ]

Вложение:
v2.png
v2.png [ 27.51 Кб | Просмотров: 831 ]


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 17:55 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Проблема в том, что RAM-функция может не использовать в своей работе функции, расположенные во Flash, а может использовать одну/две/восемь. В результате этого в начале RAM-функции будут расположены указатели на используемые функции, что сдвигает ее точку входа в сторону увеличения адресов. При компиляции мне этот факт вообще не мешает, а вот в рантайме, когда загружаю другую функцию, проц падает в HardFault...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 18:17 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
alm604 писал(а):
а вот в рантайме, когда загружаю другую функцию, проц падает в HardFault...
Что значит загружаю? Компилятор всё сам делает. Что вы там загружаете?
Вложение:
v3.png
v3.png [ 126.82 Кб | Просмотров: 817 ]
Вложение:
v4.png
v4.png [ 138.38 Кб | Просмотров: 817 ]

Ничто никуда не падает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 22:31 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Стыдновато код выкладывать, но...
Код:
void load_app(unsigned char num_app){
  unsigned int lenth, i;
  unsigned long addr=0x6000;
  unsigned long sram_addr=0x2000e000;
  spi_load_sector(addr);
  lenth = spi_buffer[6];
  lenth = lenth << 8;
  lenth += spi_buffer[7];
  while(lenth){
    addr+=0x100;
    spi_load_sector(addr);
    for(i=0;i<256;i++){
      *(unsigned char *) (sram_addr) = spi_buffer[(unsigned char)i];// Тут, думаю, Вы поймёте, о чем речь
      sram_addr++;
      lenth--;
      if(!lenth){
        break;
      }
    }
  }       
}


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 22:40 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
У Вас функции, хоть и в SRAM, но они туда при инициализации копируются из внутренней Flash МК. У меня функция загружается в рантайме из SPI Flash. Причем любая из имеющихся по желанию пользователя. Я пытаюсь МК использовать, как процессор. Не я первый. Фразы типа "Так оно же медленно будет" ни к чему. Меня устраивает скорость. Мне нужна гибкость. И количество памяти пока тоже не беспокоит. Будет мало - добавлю SRAM по FSMC. Видел подобное тут http://we.easyelectronics.ru/STM32/stm32-i-dzen-kompilyaciya-i-zapusk-otdelnyh-programm.html, но малопонятно, как там сделано.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 22:46 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
Я думаю, стоит загружаемую программу скомпилировать с того адреса, куда вы её загружаете и в таком виде хранить на флэшке.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 14 ноя 2020, 23:22 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Ок, давайте я попробую еще подробнее описать суть проблемы...
Область SRAM для загружаемых программ 2000E000 - 2000FFFF.
Первая программа:
Код:
void simple_function(void){
  for(i=0;i<16;i++){
    lcd_print(i); // <<< lcd_print находится во flash, аналогия с bios функциями. Нафига нам писать стандартные IO, когда RAM не так много?
  }
}

Тут для вызова функции lcd_print() добавляется винир (ссылка, дальний вызов функции, как хотите) по адресу 80002000, к примеру.
Вся клоака в том, что ссылка (far_jump, винир) добавляются при компиляции до кода simple_function! Указатель 32 бита, значит Entry_point для simple_function тут 0x2000E0004!
Теперь я скомпилил функцию
Код:
void complex_function(void){
  for(i=0;i<16;i++){
    lcd_print(hex(i)); //lcd_print там же, hex() по соседству (например 80002020)
  }
}

Теперь мы имеем уже две функции, вызываемые из flash (lcd_print(), hex()). Два винира, +8 байт до Entry_point функции complex_function. Но ее адрес-то для RAM_function тот же.
В итоге первый код:
Код:
0x2000E000 : Veneer 0x80002000  //lcd_print()
0x2000E004 simple_function(){  // Entry_point here

И второй:
Код:
0x2000E000 : Veneer 0x80002000  //lcd print()
0x2000E004 : Veneer 0x80002020  //hex()
0x2000E008 complex_function(){  // Entry_point here now!

И я не знаю как зарезервировать таблицу адресов в начале или переместить ее в конец функции((


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 13:11 
Старожил
Аватара пользователя

Зарегистрирован: 28 янв 2010, 20:18
Сообщения: 603
А почему компилятор должен функцию обязательно в начало положить? Хотите сделать бинарный API для вызова, так "прибейте" где-нибудь в начале с помощью скрипта линкера (или что там в IAR?) указатель на точку входа. А лучше сразу структуру-описание добавить.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 14:21 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2900
Откуда: Санкт-Петербург
Я правильно понял, что у вас функция скомпилена куда надо (под исполнение из RAM), но вызываете вы её не по адресу функции, а по адрусу отведённого для неё участка RAM?
А адрес функции при компиляции положить в табличку, живущую во flash, никак, что ли? (всё равно если в RAM больше одной функции – это придётся сделать)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 14:54 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
Сделать по аналогии с таблицей векторов прерывания. Загружать модуль с функциями вместе с этой таблицей. И никакого __ramfunc тут не надо. Вы же руками без помощи компилятора загружаете.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 18:33 
Заглядывает иногда

Зарегистрирован: 27 фев 2014, 11:50
Сообщения: 33
Position independent code?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 20:49 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
В файл линкера добавлен регион RAM_func_region (0x2000E000-0x2000FFFF), убавлен регион RAM_region (верхняя граница с 0x2000FFFF до 0x2000DFFF, чтоб стек начинался ниже)
Show

Далее я пишу большую ram_функцию show_dump, которая использует большое количество функций во flash.


Вложения:
Комментарий к файлу: В регистре 0 передается аргумент функции, тут ок. Вызов функции по виниру...
0.png
0.png [ 9.24 Кб | Просмотров: 657 ]
Комментарий к файлу: Entry point 0x2000E049 (значение в регистре R12). Ну допустим...
1.png
1.png [ 12.99 Кб | Просмотров: 657 ]
Комментарий к файлу: А теперь понятно, почему 0x2000E049 - там куча виниров в начале. Для всех используемых функций во flash.
2.png
2.png [ 75.35 Кб | Просмотров: 657 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 20:56 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
И на каждую функцию во flash имеется винир. Мне было бы пофиг, если б они были после ram_функции.
Далее я меняю функцию на более мелкую с тем же именем. Допустим, я пишу следующую загружаемую программу. Адрес входа изменился. Оно и понятно. Эта функция использует всего пару функций flash.


Вложения:
Комментарий к файлу: Для каждой из них виниры... Но это меня мало беспокоит.
3.png
3.png [ 24.73 Кб | Просмотров: 656 ]
Комментарий к файлу: Вызов из ram_function функции, находящейся во flash
4.png
4.png [ 5.82 Кб | Просмотров: 656 ]
Комментарий к файлу: Оп, а Entry point уже 0x2000E019! А почему?
5.png
5.png [ 5.89 Кб | Просмотров: 656 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:00 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Ну и еще момент... Кто-нибудь может подсказать ключевые слова для переменных и констант, чтоб они хранились в районе оперативки? Я сейчас только обнаружил, что константы попали во flash, что недопустимо.


Вложения:
Комментарий к файлу: Для новой ram_функции таблица виниров всего из пары пунктов. Вот что сдвинуло точку входа.
7.png
7.png [ 9.99 Кб | Просмотров: 656 ]
Комментарий к файлу: А еще и сообщения записываются во flash. Вот это для меня сейчас новость...
q.png
q.png [ 151.8 Кб | Просмотров: 656 ]
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:01 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Immortal_Buka писал(а):

Смотрел. Один пример для ARM7TDMI, второй - бутлодырь. Похоже, но не то.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:05 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
amaora писал(а):
"прибейте" где-нибудь в начале с помощью скрипта линкера (или что там в IAR?) указатель на точку входа. А лучше сразу структуру-описание добавить.

Вы переоцениваете мой опыт в таких вопросах. Я редко на форумах задаю вопросы, только когда уже хочется подать на платку вольт 220-380, в остальном стараюсь гуглить. С линкерами не знаком. Область задал? - Ну клади сюда, чего мудрить. Нет же, ссылки эти. Как указать, куда ссылки разместить - не знаю. Трудно раскуривать ARM после 8-биток и x86...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:10 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
aamonster писал(а):
Я правильно понял, что у вас функция скомпилена куда надо (под исполнение из RAM), но вызываете вы её не по адресу функции, а по адрусу отведённого для неё участка RAM?

Тут, думаю, по скриншотам будет понятно. Как еще вызвать функцию - я не знаю.
aamonster писал(а):
А адрес функции при компиляции положить в табличку, живущую во flash, никак, что ли? (всё равно если в RAM больше одной функции – это придётся сделать)

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


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:12 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
VladislavS писал(а):
И никакого __ramfunc тут не надо. Вы же руками без помощи компилятора загружаете.

А можно подробнее? Я не понимаю, как вызвать функцию, даже зная ее адрес, не прибегая к ассемблеру (Thumb для меня чот сложноват)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:35 
Старожил

Зарегистрирован: 06 июн 2018, 22:30
Сообщения: 551
Откуда: Киев
Не сможет оно так работать. Попробуйте все что вы подгружаете вызывать через указатели на эти функции. На а адреса вы должны знать.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:53 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
alm604 писал(а):
Я не понимаю, как вызвать функцию, даже зная ее адрес, не прибегая к ассемблеру
Вызов функции по указателю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 21:56 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
Короче, пока работает вот такой костыль... Перед вызовом функции в оперативке ищу ее точку входа, так как виниры выравниваются по 8 байт и имеют один и тот же байт в начале (0xDF)
Код:
unsigned long search_entry(void){
  unsigned long sram_addr = 0x2000E000;
  while(*(unsigned char *) (sram_addr) == 0xDF){
    sram_addr+=8;
  }
  return sram_addr;
}

В дебаггере видно, что адрес возвращается в регистре 0.
После того, как адрес найден,
Код:
asm("MOV PC, R0");

Не самое лучшее решение, но работает)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 22:00 
Заглядывает иногда
Аватара пользователя

Зарегистрирован: 27 фев 2011, 21:32
Сообщения: 163
VladislavS писал(а):
alm604 писал(а):
Я не понимаю, как вызвать функцию, даже зная ее адрес, не прибегая к ассемблеру
Вызов функции по указателю.

Это не работает. Не издевайтесь. Вызвать функцию, не зная ее точки входа не получится. Я выше на скриншотах уже как мог всё попытался объяснить. А точка входа меняется в зависимости от количества вызовов функций во flash.
В любом случае, спасибо за попытки помочь.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 22:26 
Старожил

Зарегистрирован: 06 июн 2018, 22:30
Сообщения: 551
Откуда: Киев
alm604 писал(а):
Это не работает. Не издевайтесь. Вызвать функцию, не зная ее точки входа не получится.
В любом случае, спасибо за попытки помочь.

Так ты же ее сам в ОЗУ и переносишь и ты не знаешь ее адрес?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: RAM Executing
СообщениеДобавлено: 15 ноя 2020, 22:31 
Старожил
Аватара пользователя

Зарегистрирован: 13 янв 2018, 21:36
Сообщения: 1657
alm604 писал(а):
Вызвать функцию, не зная ее точки входа не получится.
Вам же написали, сделайте структуру, состоящую из указателей на функции и инициализируйте её адресами функций. Примерно как таблица векторов прерываний, только в таблице векторов все функции одного типа, а тут разные будут. Через структуру по указателю и вызывайте.

alm604 писал(а):
Не издевайтесь.
Это вы над нами издеваетесь. Хотя, оно и понятно. Если бы вы могли понятно описать проблему, то знали бы как её решить. Правильный вопрос - половина ответа.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 34 ]  На страницу 1, 2  След.


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB