|
Чтение boot-области из приложения |
|
|
|
 |
Ответов
(1 - 11)
|
Sep 8 2008, 19:54
|

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

|
Цитата(Огурцов @ Sep 8 2008, 21:17)  Как это лучше сделать ? Конечно, бутлоадер возможно доработать. В загрузчик по изветному адресу (например, на используемый в загрузчике вектор прерывания) вставляется функция, возвращающая версию. На следующий вектор вешается такая же функция, возвращающая серийный номер и т.д. Функция вида Код Get_Serial: LDI r24, lo8(SERIAL) LDI r25, hi8(SERIAL) RET При необходимости, AVReal умеет прописывать серийные номера и константы в такие функции.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 9 2008, 07:26
|
Гуру
     
Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588

|
С использованием таблицы векторов прерываний идея понравилась. Может быть и возможности компилятора (WinAVR/GCC) использовать по инициализации таблицы векторов ? Типа: Код ISR(SIG_####) { asm { pop pop jmp Get_version } } Правда, со стеком придется поизвращаться. Или есть более прямой путь объяснить компилятору, чтобы он проинициализровал определенный вектор адресом произвольной функции ?
Сообщение отредактировал Огурцов - Sep 9 2008, 07:27
|
|
|
|
|
Sep 9 2008, 07:40
|

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

|
Цитата(Огурцов @ Sep 9 2008, 10:26)  Или есть более прямой путь объяснить компилятору, чтобы он проинициализровал определенный вектор адресом произвольной функции ? Написать ее на ассемблере. Или написать обычную функцию uint16_t GetSerial() { return 0xffff; } и на ассемблере поставить JMP на нее в нужный вектор. Или поместить эту функцию в отдельную секцию, а секцию разместить по известному адресу, не обязательно на вектора, можно и в конце загрузчика. Я делаю именно так. Ну если хочется на вектора, то вот так: Код #define VERSION 12345
ISR(SIG_####, ISR_NAKED) { asm volatile ("\n\t" "LDI r24, %A0 \n\t" "LDI r25, %B0 \n\t" "RET \n\t" : :"i" ((uint16_t)VERSION) :r23,r24 ) } Но я бы к векторам не пристраивался - мало ли потом переделаете загрузчик и вектора понадобятся. Обычные функции гибче: Код uint16_t GetVersion() __attribute__((section(".get_version"))); uint16_t GetVersion() { return VERSION; } или так:
int16_t GetVersion() __attribute__((section(".get_version"))); uint16_t GetVersion() { uint16_t Version; asm volatile ("\n\t" "LDI %A0, %A1 \n\t" "LDI %B0, %B1 \n\t" "RET \n\t" :"=r"(Version) :"i" ((uint16_t)VERSION) ) return version; }
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 9 2008, 09:16
|
Гуру
     
Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588

|
Ага, naked - замечательное слово. 10x! Получилось примерно так: Код #define VERSION 12345
uint16 Get_version() { return VERSION; }
__attribute__((naked)) ISR(SIG_OVERFLOW0) // ISR_NAKED почему-то не берет { asm volatile ( "rjmp Get_version \n\t" ); } Приложение ничего не знает о загрузчике, поэтому вектора (либо как-то по другому, но с _фиксированными_ адресами) отличное решение. Прерывания в загрузчике не нужны, если когда и потребуются, то это будет уже совсем другая история. Теперь остается вопрос, как в приложении красиво вычислить адрес ? Т.к. размеры вектора в таблице и размеры бутовой области у разных камней разные. Тупо загнать в ifdef`ы или в GCC опять предусмотрена какая-нибудь хитрость(атрибут) ?
|
|
|
|
|
Sep 9 2008, 09:50
|

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

|
Цитата(Огурцов @ Sep 9 2008, 12:16)  Теперь остается вопрос, как в приложении красиво вычислить адрес ? Т.к. размеры вектора в таблице и размеры бутовой области у разных камней разные. Кристаллы бывают разные, но на этапе компиляции, как правило, известно, для какого кристалла компилится и сколько в этом кристалле отдано под загрузчик. Точнее, точно известны адреса этих функций. Я их указываю в скрипте линкера или командной строке: Код *.cpp: extern "C" uint16_t SerialNo(); *.c: extern uint16_t SerialNo();
makefile: LDFLAGS += -Wl,--defsym,SerialNo=0x1FFA или *.ld: SECTIONS { .... } SerialNo = 0x1FFA; Цитата(Огурцов @ Sep 9 2008, 12:16)  Получилось примерно так: Код __attribute__((naked)) ISR(SIG_OVERFLOW0) // ISR_NAKED почему-то не берет { asm volatile ( "rjmp Get_version \n\t" ); } ISR_NAKED появилось в последних версиях, возможно в вашей еще нет. Теперь посмотрите в листинг. У вас в области векторов получился rjmp на обработчик, из которого уже rjmp на функцию. Разместите уже всю функцию в обработчик, сэкономите место и время.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 9 2008, 13:26
|
Гуру
     
Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588

|
Цитата(Сергей Борщ @ Sep 9 2008, 09:50)  Точнее, точно известны адреса этих функций. Я их указываю в скрипте линкера или командной строке: Да, это красиво. Но в данном случае вызывает проблемы - в случае, если вносим изменения в бутлоадер, автоматически получается два make`а и два bin`а. Или в следующий раз еще больше. То, что бутлоадер будет меняться я даже не сомневаюсь, поэтому вариант с использованием векторов мне понравился гораздо больше. Цитата(Сергей Борщ @ Sep 9 2008, 09:50)  ISR_NAKED появилось в последних версиях, возможно в вашей еще нет. Да, что-то такое, видимо. Цитата(Сергей Борщ @ Sep 9 2008, 09:50)  У вас в области векторов получился rjmp на обработчик, из которого уже rjmp на функцию. Разместите уже всю функцию в обработчик, сэкономите место и время. Да, потенциально два лишних jamp`а, но м.б. будет вызов более сложных функций, типа crc посчитать, которые оптимизировать и руками прегонять в ассемблер проблемно да, думаю, и не нужно. А в случае с версией да, один jamp можно выкинуть. С векторами, похоже, будет так: Код #define GET_VERSION_VECTOR 1
__attribute__((naked)) ISR(_VECTOR(GET_VERSION_VECTOR)) ... Ничего лучше пока не придумалось
|
|
|
|
|
Sep 10 2008, 07:43
|

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

|
Цитата(Огурцов @ Sep 9 2008, 16:26)  Да, это красиво. Но в данном случае вызывает проблемы - в случае, если вносим изменения в бутлоадер, автоматически получается два make`а и два bin`а. Этого я не понял. У меня эти функции идут в самом конце области загрузчика. Просто подряд, как обычные функции без векторов и лишних jmp на них. Поскольку менять их у меня нет необходимости, то они прибиты гвоздями и никакое изменение загрузчика их не затрагивает. Одна тонкость- поскольку сам загрузчик их не использует, линкер может выкинтуть их по --gc-section. Поэтому в скрипте линкера надо их секцию поместить в KEEP()
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Sep 10 2008, 08:06
|
Гуру
     
Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588

|
Цитата(Сергей Борщ @ Sep 10 2008, 07:43)  Этого я не понял. Т.к. исходим из того, что загрузчик в дальнейшем м.б. модифицирован (вектора потребуются), нет и гарантий, что не будут модифицированы такие функции, как get_version, get_serial_number, get_crc, т.е. адреса последних потенциально могут измениться. Это повлечет за собой то, что одно и то же приложение д.б. скомпилировано дважды, для каждого варианта загрузчика. Фактически будем иметь произведение числа версий приложения на число версий загрузчика, а это жутко. Вектор(ы) позволят организовать хоть какую-то совместимость приложений и загрузчиков. Цитата(Сергей Борщ @ Sep 10 2008, 07:43)  Поэтому в скрипте линкера надо их секцию поместить в KEEP() Согласен. зы: хотя места в бут-секции мало и все нужные фичи уже не входятся.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|