Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таблица вызова функций. Как?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
EXeGLuMATOR
День добрый.
Имеется желание и необходимость сделать что-то типа BIOS для LPC23хх. Мысль в следующем - загружается что-то типа лоадера, который управляет камнем, также в нем есть базовый код для работы с периферией. Он един для всех проектов. Софт верхнего уровня делается отдельно и грузится выше адресами. Как сделать, чтобы из него можно было обращаться к базовым функциям?
Мысль одна - сделать табличку с адресами соотв. функций и буферов и верхним софтом ее юзать. Только как ее заполнять? Поскольку после каждой компиляции может меняться и размер и, как следствие, "раскладка" функций в памяти.
scifi
Цитата(EXeGLuMATOR @ Sep 7 2011, 12:54) *
Мысль одна - сделать табличку с адресами соотв.

Вообще-то можно придумать множество способов входа в BIOS. Тот же SWI, например.
Интересно было бы посмотреть, как сделано StellarisWare. У них некая библиотека зашита в ПЗУ.

Цитата(EXeGLuMATOR @ Sep 7 2011, 12:54) *
Только как ее заполнять? Поскольку после каждой компиляции может меняться и размер и, как следствие, "раскладка" функций в памяти.

Можно сделать массив с таблицей указателей на функции и разместить её по фиксированному адресу.
EugenyAM
Достаточно одного фиксированного адреса, по нему делается вызов, который возвращает указатель на массив указателей на все функции BIOS, если состав функций может быть разным, можно предусмотреть какой-либо заголовок с дескрипторами из которого клиентское приложение может достать всю информацию для работы с BIOS.
Дальше эти указатели можно присвоить некой структуре и пользовать вызовы например типа BIOS.UartInit();
Запрос и присвоение структуры можно вынести в отдельную функцию типа BIOS_Init(Struct TBIOS* BIOS), т.е. прикладной программист включает эту функцию в свой код, а дальше работает с вызовами из структуры.


Тут пример написания обработчика SWI

http://www.microchip.su/showthread.php?t=4860

Программное прерывание SWI - тоже фиксированная точка входа. При этом еще происходит повышение уровня с пользовательского до системного.

AlexandrY
Цитата(EXeGLuMATOR @ Sep 7 2011, 11:54) *
Имеется желание и необходимость сделать что-то типа BIOS для LPC23хх.


Зачем в в таком примитивном микроконтроллере BIOS?
BIOS создавался чтобы изолировать юзера от меняющегося хардваре.
Здесь же хардваре жестко задано. В пределах семейства различия мизерные.
Т.е. подражание BIOS приведет к квадратному колесу.
Способ изоляции юзера от сложностей хардваре удачно придуман в проекте Arduino. Его и следует копировать, ИМХО.
e-serg
Цитата(EXeGLuMATOR @ Sep 7 2011, 17:54) *
Мысль одна - сделать табличку с адресами соотв. функций и буферов и верхним софтом ее юзать. Только как ее заполнять?

Допустим так сделать примерно так
Код
uint8_t data[4096];
int flash_write(uint32_t addr, uint8_t *data, int size); //некая функция
typedef struct{
    uint8_t VER_ID;
    int (*flash_write)(uint32_t, uint8_t*, int);
}FS; // в этой структуре перечислим
const FS __attribute__((section(".boot_func"))) fs = {0, &flash_write}; // разместим например по адресу 0x100UL с помощью линкера
const FS *fs2 = (FS *)0x100UL; // 0x100UL - адрес куда разместили структуру.

    fs.flash_write(250, data, 196); // варианты вызова одной функции.
    fs2->flash_write(250, data, 196);
    flash_write(250, data, 196);


Цитата(AlexandrY @ Sep 8 2011, 14:27) *
Зачем в в таком примитивном микроконтроллере BIOS?

например одни и те же функции обработки данных в загрузчике и приложении.
тоже шифрование, зачем по два экземпляра кода.
EXeGLuMATOR
Цитата(e-serg @ Sep 8 2011, 10:22) *
например одни и те же функции обработки данных в загрузчике и приложении.
тоже шифрование, зачем по два экземпляра кода.

Именно для мелких камней это и применимо. Тот-же ЮСБ и в загрузчике и в приложении - нет лишнего кода в приложении. Просто заполнил буфер, скомандовал на передачу. В этом и идея - все железо живет своей жизнью. Если оно нужно - его стартуем пользовательским софтом, если нет - то нет.

Спасибо. Вроде осознал по таблице. Т.е. как заполнить более или менее ясно, будем пробовать.
Теперь следующий вопрос, по этой же теме.
Лоадер работает, функции известны, периферия запущена (предполагается операционка, от Кейла). Т.е. лоадер - программа сама в себе. Верхнее приложение лежит во флэш с какого-то фиксированного адреса.
Стартовая функция (задача) приложения лежит по известному адресу и стартовать его не проблема. Каким образом компилировать пользовательскую программу, чтобы избежать появления лишнего кода? Т.е. чтобы был голый код приложения, после запуска которого он живет своей жизнью? Ну, насколько ему дает лоадер.
Тут скорее наоборот - лоадер выполняет функции ядра операционки, грубо говоря. А основной код может быть загружен в принципе любой, заточенный под такое применение, естественно. Т.е., например, идет обмен по ЮСБ - его сначала ловит лоадер и, если то что там ходит не относится к его работе (например обновление пользовательского софта и т.п.) - то пакет передается в пользовательское приложение. Как-то так.
Опять-же вопрос отладки. Ладно, лоадер и пользовательский софт во время отладки можно компилить как единое целое, а нужное потом как-то вырезать. Опять-же, как?
scifi
Похоже на изобретение велосипеда а-ля полновесная ось с запуском приложений.
Откладываем в сторону большой вопрос "нафиг?" и вообще вопрос о целесообразности такого подхода в микроконтроллерных приложениях.
Ось надо сначала спроектировать, в потом уже реализовывать. Надо описать ABI, под которым будет исполняться пользовательское приложение. Надо расписать функциональность и сферы ответственности ядра и приложения. И т.д. А вы занимаете свою голову второстепенными вопросами типа "Каким образом компилировать пользовательскую программу, чтобы избежать появления лишнего кода?"
EXeGLuMATOR
Цитата(scifi @ Sep 8 2011, 12:35) *
Похоже на изобретение велосипеда а-ля полновесная ось с запуском приложений.
Откладываем в сторону большой вопрос "нафиг?" и вообще вопрос о целесообразности такого подхода в микроконтроллерных приложениях.
Ось надо сначала спроектировать, в потом уже реализовывать. Надо описать ABI, под которым будет исполняться пользовательское приложение. Надо расписать функциональность и сферы ответственности ядра и приложения. И т.д. А вы занимаете свою голову второстепенными вопросами типа "Каким образом компилировать пользовательскую программу, чтобы избежать появления лишнего кода?"


В чем-то может и велосипед. А смысл прост. Есть устройство, нужно обеспечить запуск этих самых приложений. Ресурсы ограничены. Т.е. код лоадера + еще точно такой-же код в основном приложении - как-то расточительно, хоть и просто в реализации. И просто не лезет в камень. Еще очень большой блок данных во флэш лежит. Лоадер не меняется, только алгоритм обработки этих данных в зависимости от внешних воздействий. Вот и хочется максимальной скорости и простоты смены этого алгоритма пользователем на установленном изделии.
scifi
Цитата(EXeGLuMATOR @ Sep 8 2011, 12:54) *
Лоадер не меняется, только алгоритм обработки этих данных в зависимости от внешних воздействий. Вот и хочется максимальной скорости и простоты смены этого алгоритма пользователем на установленном изделии.

Возможно, подойдёт подход с интерпретатором скриптового языка. Он как раз обеспечивает простоту загрузки нового скрипта. Но если нужно быстродействие, то интерпретатор может не подойти.
Я использовал Pawn. Отличная вещь.
EXeGLuMATOR
Цитата(scifi @ Sep 8 2011, 13:00) *
Возможно, подойдёт подход с интерпретатором скриптового языка. Он как раз обеспечивает простоту загрузки нового скрипта. Но если нужно быстродействие, то интерпретатор может не подойти.
Я использовал Pawn. Отличная вещь.


Спасибо. Интересная вещь. Но что-то насчет простоты - не совсем понятно (точнее совсем непонятно) как его в камень вкорячить и соотв заставить работать с периферией типа Ethernet и USB.
Да и скорость тоже очень немаловажно - релтайм обработка сигналов таки. Пусть не навороченная но тем не менее - много ее.
AlexandrY
Цитата(EXeGLuMATOR @ Sep 8 2011, 11:54) *
В чем-то может и велосипед. А смысл прост. Есть устройство, нужно обеспечить запуск этих самых приложений. Ресурсы ограничены. Т.е. код лоадера + еще точно такой-же код в основном приложении - как-то расточительно, хоть и просто в реализации. И просто не лезет в камень. Еще очень большой блок данных во флэш лежит. Лоадер не меняется, только алгоритм обработки этих данных в зависимости от внешних воздействий. Вот и хочется максимальной скорости и простоты смены этого алгоритма пользователем на установленном изделии.


Здесь годятся только либы. Отдаете пользователю скомпилированные либы со средством линковки, и он сам их прилинкует когда надо.

Либо загрузчик объектного кода пользователя реализуете сами на своей платформе. Но это гораздо сложнее.
psL
Вещь полезная. Удобно при обновлении ПО, когда меняется только пользовательская логика, а bsp остается прежним. Особенно когда bsp существенно больше пользовательского кода. Либо когда объем пользовательского кода+bsp больше объема памяти системы.
Динамически при загрузке связывать со всеми функциями BSP может быть затруднительно ввиду большого количества этих функций. Нужно как-то линковать статически с библиотекой BSP, чтобы адреса функций либы BSP оставались неизменными, и чтобы фирмварь от версии к версии вызывала их по одним и тем же адресам.
В свое время пробовал настроить линкер кейла - не получилось( Интересно как это реализовано у Тексас на его кортексах?
EXeGLuMATOR
Да, видимо так. Осталось разобраться как это сделать, по уму.
Alechek
Цитата(psL @ Sep 9 2011, 22:54) *
Вещь полезная. Удобно при обновлении ПО, когда меняется только пользовательская логика, а bsp остается прежним. Особенно когда bsp существенно больше пользовательского кода. Либо когда объем пользовательского кода+bsp больше объема памяти системы.

Бред насчет полезной вещи.
Для загрузчика BSP, как правило, весьма мало. А вот пользовательскому приложению по мере увеличения функционала может потребоваться новое BSP. Или исправление ошбок в существующем.
Так что обновление BSP тоже надо предусматривать. То есть линковка функций BSP по статическим адресам отпадает.
EXeGLuMATOR
Цитата(Alechek @ Sep 14 2011, 11:19) *
Бред насчет полезной вещи.
Для загрузчика BSP, как правило, весьма мало. А вот пользовательскому приложению по мере увеличения функционала может потребоваться новое BSP. Или исправление ошбок в существующем.
Так что обновление BSP тоже надо предусматривать. То есть линковка функций BSP по статическим адресам отпадает.


Ну, это называется эволюцией. Соотв, как правило к этому времени назревает и изменение аппаратной части. И получается новая версия аппаратной платформы. Местами sm.gif совместимая со старой.
Кстати, ничего не мешает в пользовательском модуле реализовывать и новые функции, отлаживать, а потом, по мере развития переносить в BSP
Alechek
Возможно. В итоге часть BSP зашита, часть в пользовательском приложении.
Вот только не понимаю, нафига это для LPC23XX?
К примеру, в моем приложении для 2388 всего 100 кб, из них
1. загрузчик (постоянная часть) - 12 кб
2. библиотеки компилятора - 20 кб
3. драйвера периферии - 19 кб
4. ядро OS - 2.5
5. собственно приложение - 46 кб

Итого под обновление уходит 88 кб. Стоит ли создавать себе болячку на пятой точке опоры ради того чтобы уменьшить размер обновления на 19/88 = 20% ?
EXeGLuMATOR
Цитата(Alechek @ Sep 14 2011, 15:57) *
2. библиотеки компилятора - 20 кб

А для чего 2?
Я предполагаю, что 1, 3, 4 - как раз и будет постоянная часть. А вот приложение - все остальное и объем его может быть весьма значителен. Смысл этой канители - на ходу менять алгоритм работы устройства, например дистанционно. Не прерывая его работы. Ну или с минимальным простоем.
Alechek
2 - никуда от нее не денешся. стандартная библиотека "С"
Хочеца поизвращаться - удачи! cool.gif
psL
Цитата(Alechek @ Sep 14 2011, 11:19) *
Бред насчет полезной вещи...

Бред насчет бреда :D
Подобный вопрос на форуме периодически возникает, а внятного ответа на него что-то пока не наблюдается...

_Pasha
Цитата(psL @ Sep 15 2011, 15:02) *
Подобный вопрос на форуме периодически возникает, а внятного ответа на него что-то пока не наблюдается...

Давным - давно zltigo давал внятный ответ: не жлобиться и закладывать внешнюю NVRAM
psL
Цитата(_Pasha @ Sep 16 2011, 05:32) *
Давным - давно zltigo давал внятный ответ: не жлобиться и закладывать внешнюю NVRAM

Непонятно, чем внешняя NVRAM спасет. Еще не факт что у MCU есть поддержка внешней памяти, не говоря об усложнении конструкции и увеличении стоимости ("...не мы такие - жисть такая...").
Интересует ответ на конкретный вопрос: как линковать свое приложение с бинарной библиотекой на кристалле в "народных" средствах разработки? В виде примера или ссылки на пример.
EXeGLuMATOR
Ну, насколько я понимаю - просто сделать табличку вызовов функций и адреса буферов/аргументов этого самого лоадера - как, например, обращаемся же мы к IAP тому-же, в конце концов. С этим боле или менее понятно. С пользовательским кодом - повеселее. Мало того, что все стартапы тащить нужно, так еще и стартовать этот код как-то. Хотя вызывать какую-либо стартовую функцию или задачу, которая точно знает где что лежит в юзерском коде, поскольку и является частью всего этого.
Вопрос в том, как избавиться от лишнего кода в пользовательской части? И как ограничить пользовательскую часть при компиляции, чтобы компилер не лез в области используемые лоадером?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.