Компілюючий код для запуску із зовнішньої ОЗУ


13

Я розглядаю конструкції для мінімалістичної ігрової системи на основі PIC18F85J5. Частина мого дизайну полягає в тому, що ігри можна завантажувати з SD-карти без перепрограмування мікросхеми або миготіння пам'яті програми. Я вибрав цей чіп, оскільки він має зовнішній інтерфейс пам'яті, який дозволить мені запускати код із зовнішньої SRAM.

Основна ідея полягає в тому, що внутрішня пам'ять програми буде містити інтерфейс для перегляду sd карти, і як тільки користувач вибере програму, він скопіює шістнадцятковий файл з sd карти на зовнішній таран, а потім перескочить виконання у зовнішній простір оперативної пам'яті .

Внутрішня пам'ять програми також матиме різні бібліотеки для графіки, введення контролера та інші різні утиліти.

Я досить впевнений, що знаю, як зробити так, щоб внутрішні деталі прошивки справно працювали. Проблема полягає у створенні програм для запуску із зовнішньої ОЗУ. Це не так, як націлювання на звичайний малюнок, і йому потрібно знати, що функції бібліотеки є у внутрішній пам'яті, але не перекомпілювати їх, лише посилатися на них. Він також повинен почати використовувати адреси відразу після 32k внутрішнього спалаху, а не з нуля. Чи є хороший спосіб скласти програму, використовуючи такі типи обмежень?

Я використовую IDE MPLab, але я не надто знайомий з ним, або як зробити такий тип налаштування.


Одне з найкращих питань, яке я тут бачив за деякий час ... Я з нетерпінням чекаю почуття ідей та відповідей.
Джон Л

Деякі цікаві альтернативні підходи обговорюються в електроніці.stackexchange.com
questions/5386/…

Я це бачив, але вони в основному рекомендують писати на флеш, чого я хотів би уникнути. Моя апаратна конструкція буде нагадувати цифру 6 у примітці до додатка у прийнятій відповіді.
captncraig

Відповіді:


8

У вас є два окремих питання:

  1. Побудова коду для зовнішнього діапазону адрес RAM.

    Це насправді дуже просто. Все, що вам потрібно зробити, - це зробити файл-посилання, який містить лише діапазони адрес, які ви бажаєте зайняти. Зауважте, що вам потрібно не тільки резервувати певний діапазон адрес пам'яті програми для цих зовнішніх додатків, але і деякий простір оперативної пам'яті. Цей простір оперативної пам’яті, як і адреси пам'яті програми, потрібно фіксувати та знати. Просто зробіть доступними лише ті фіксовані та відомі діапазони адрес для використання у файлі посилання. Не забудьте зробити їх НЕ доступними у файлі посилання базового коду.

    Після того, як базовий код завантажує нову програму у зовнішню пам'ять, він повинен знати, як її виконати. Найпростіше, мабуть, розпочати виконання в першому зовнішньому місці оперативної пам'яті. Це означає, що вашому коду знадобиться один розділ КОДУ за цією абсолютною початковою адресою. Це містить GOTO праворуч, в решті коду, який буде переміщений.

  2. Зв’язування програм із підпрограм бібліотеки в базовому коді.

    Немає одразу простого способу зробити це за допомогою існуючих інструментів Microchip, але це не так вже й погано.

    Набагато більшим питанням є те, як ви хочете боротися зі змінами базового коду. Спрощена стратегія полягає у створенні базового коду, запустіть програму над отриманим картографічним файлом для збирання глобальних адрес, а потім накажіть файл імпорту з операторами EQU для всіх глобально визначених символів. Цей файл імпорту буде потім включений у весь код програми. Нічого не може пов'язувати, оскільки вихідний код програми по суті містить фіксовану посилання на точки введення базового коду.

    Це легко зробити і буде працювати, але врахуйте, що станеться при зміні базового коду. Навіть незначне виправлення помилок може призвести до переміщення всіх адрес, і тоді всі існуючі коди додатків не будуть корисними та повинні бути відновлені. Якщо ви ніколи не плануєте надавати оновлення базового коду, не оновлюючи всі додатки, то, можливо, ви можете піти з цього, але я думаю, це погана ідея.

    Кращий спосіб - це мати визначену область інтерфейсу за обраною фіксованою відомою адресою в базовому коді. Буде один GOTO для кожної підпрограми, яку може викликати код програми. Ці GOTO розміщуватимуться за фіксованими відомими адресами, а зовнішні додатки дзвонять лише до тих локацій, які потім перескакують туди, куди підпрограма фактично опинилась у цій збірці базового коду. Це коштує 2 програмних пам'яті на кожну експортовану підпрограму та два додаткові цикли під час виконання, але я думаю, що це варто того.

    Для цього вам потрібно автоматизувати процес генерації GOTO і результуючого файлу експорту, який зовнішні додатки імпортуватимуть для отримання адрес підпрограми (фактично перенаправлення GOTO). Можливо, вам вдасться вчинити з розумним використанням макросів MPASM, але якби я робив це, я б точно використовував мій препроцесор, оскільки він може записувати у зовнішній файл під час попередньої обробки. Ви можете записати макрос препроцесора, щоб кожен перенапрямок міг бути визначений одним рядком вихідного коду. Макрос виконує всі неприємні речі під кришкою, які мають генерувати GOTO, зовнішнє посилання на фактичну цільову процедуру та додавати відповідний рядок до файлу експорту з відомою постійною адресою цієї програми, все з відповідними іменами. Можливо, макрос просто створює купу змінних препроцесора з регулярними іменами (kindof, як масив, що розгортається під час виконання), а потім файл експорту записується один раз після всіх макросів. Однією з багатьох речей, які мій препроцесор може зробити, що макроси MPASM не можуть - це робити рядкові маніпуляції для створення нових імен символів з інших імен.

    Мій препроцесор та купа інших пов'язаних матеріалів доступні безкоштовно на веб-сайті www.embedinc.com/pic/dload.htm .


Мені дуже подобається ідея фіксованого стрибкового столу. Я міг просто починати з кінця флеш-пам’яті і мати фіксовані місця для кожного системного виклику. Я навіть, ймовірно, міг би відійти від файлу заголовка, який підтримується вручну, з адресами всіх підпрограм, якщо я не можу розібратися з усім описаним вами вузовом препроцесора.
captncraig

5

Варіант 1: Інтерпретовані мови

Це не відповідає безпосередньо на запитання (це відмінне запитання, BTW, і я сподіваюся, що я дізнаюся з відповіді, яка безпосередньо вирішує його), але це дуже часто, коли ви робите проекти, які можуть завантажувати зовнішні програми для запису зовнішніх програм у інтерпретована мова. Якщо ресурси обмежені (що вони будуть на цьому процесорі, ви думали про використання для цього PIC32 або невеликого процесора ARM?), Звичайно обмежувати мову підмножиною повної специфікації. Ще далі по ланцюгу знаходяться мови, що стосуються домену, які виконують лише кілька речей.

Наприклад, проект elua - приклад мови, що інтерпретується з низьким ресурсом (64 кБ оперативної пам'яті). Ви можете стиснути це до 32 Кб оперативної пам’яті, якщо ви видалите деякі функції (Примітка. Це не працюватиме на вашому поточному процесорі, який є 8-бітовою архітектурою. Використання зовнішньої ОЗУ, ймовірно, буде занадто повільним для графіки). Він забезпечує швидку, гнучку мову, на якій нові користувачі зможуть легко програмувати ігри, якщо ви надаєте мінімальний API. Існує велика кількість документації для мови онлайн. Є й інші мови (наприклад, Forth та Basic), якими ви могли б користуватися подібним чином, але я думаю, що Lua - найкращий варіант на даний момент.

Так само ви можете створити свою власну мову, що залежить від домену. Вам доведеться надати більш повноцінний API та зовнішню документацію, але якби ігри були подібні, це не було б надто складно.

У будь-якому випадку, PIC18, мабуть, не є процесором, який я б використовував для чогось, що передбачає власні програми / сценарії та графіку. Можливо, ви знайомі з цим класом процесорів, але я б припустив, що це вдалий час використовувати щось із драйвером дисплея та більшою кількістю пам'яті.

Варіант 2: Просто перепрограмуйте всю справу

Якщо ви вже плануєте самостійно програмувати всі ігри на C, тоді не займіться завантаженням лише логічної гри з SD-карти. У вас є лише 32 кБ Flash для перепрограми, і ви можете легко отримати для цього 4 Гб microSD-карту. (Примітка: великі картки часто SDHC, з якими складніше інтерфейс). Якщо припустити, що ви використовуєте останній байт 32 КБ, це залишає на SD-картці 131 072 копії вашої прошивки з будь-якою логікою гри.

Є багато додатків для написання завантажувачів для PIC, як AN851 . Вам потрібно буде розробити завантажувач, щоб він займав певну область пам’яті (можливо, вгорі області пам’яті, ви б вказали це в лінкері) і вказали, що повні проекти програмного забезпечення не досягають цього регіону. Програма розповідає про це детальніше. Просто замініть "Завантажувальну секцію PIC18F452" на "Завантажувальну секцію, яку я вказую в лінкері", і це матиме сенс.

Тоді ваш завантажувач просто повинен дозволити користувачеві вибрати програму для запуску із SD-карти та скопіювати всю справу. Користувальницький інтерфейс може бути таким, що користувач повинен утримувати натиснуту кнопку, щоб увійти в режим вибору. Зазвичай завантажувач просто перевірятиме стан цієї кнопки під час скидання, і, якщо її не затримують, завантажується в гру. Якщо його утримувати, потрібно буде дозволити користувачеві вибрати файл на SD-картці, скопіювати програму і продовжувати завантажуватися в [нову] гру.

Це моя сьогоднішня рекомендація.

Варіант 3: Глибока магія, що включає збереження лише частини шестигранного файлу

Проблема з вашим передбаченим механізмом полягає в тому, що процесор не працює з API та викликами функцій, він розглядає числа - адреси, на які може перейти покажчик інструкцій, і очікує, що там буде код, який виконує виклик функції відповідно до специфікації API. Якщо ви спробуєте скласти лише частину програми, лінкер не буде знати, що робити під час дзвінка check_button_status()або toggle_led(). Ви можете знати, що ці функції існують у шістнадцятковому файлі процесора, але він повинен точно знати, за якою адресою вони перебувають.

Лінкер вже розбиває ваш код на кілька розділів; теоретично ви могли б розбити це на додаткові розділи з деякими -sectionта #pragmaзакликами. Я ніколи цього не робив, і не знаю як. Поки вищевказані два методи не підведуть мене (або хтось опублікує тут дивну відповідь), я, мабуть, не буду вивчати цей механізм, і тому я не можу навчити вас це.


Моє заперечення проти №2 полягає в тому, що флеш-пам’ять має обмежену кількість циклів стирання протягом життя мікросхеми. Я не хочу використовувати BEfier mcu, оскільки я берусь за 8-розрядний мінімалізм.
captncraig

@CMP - Він має щонайменше 10000 циклів стирання. Якщо кожен день грає в іншу гру, це триватиме до 2039 року. Спалах майже напевно переживе решту ланцюга. Я не думаю, що потрібно турбуватися з цього приводу, якщо це не аркада, яку потрібно грати десятки разів щодня.
Кевін Вермер

1
По-друге, 8-розрядний мінімалізм може виглядати круто, але це досить для програмування. Набагато простіше придбати міцний мікроконтролер і зробити його ретро, ​​ніж змусити його виглядати ретро, ​​тому що ти розсуваєш межі свого процесора.
Кевін Вермер

1
Обидва дуже справедливі моменти. Навіть якщо йдеться про низьку кількість частин, pic32 не відрізняється за вартістю або зовнішніми компонентами, ніж це, і якщо у нього 512K внутрішнього спалаху, він навіть виграє.
captncraig

Схоже, практичним рішенням буде використання pic32 та написання завантажувача для перезавантаження з SD карти. Мені б важко повторно використовувати функції як завантажувача, так і користувальницького коду, але поки я зберігаю його у спалаху завантаження 12k, він повинен надавати користувачеві коду весь чіп, і вони можуть включати всі бібліотеки, які вони хочуть у джерелі рівень.
captncraig
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.