реклама на сайте
подробности

 
 
> Чтение boot-области из приложения
Огурцов
сообщение Sep 8 2008, 18:17
Сообщение #1


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



Вообще, чтение запрещено лок-битами, но нужно прочитать несколько байт, например, версию и тип бутлоадера.
Как это лучше сделать ? Конечно, бутлоадер возможно доработать. М.б. кто линки встречал на нечто подобное ?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
Сергей Борщ
сообщение Sep 8 2008, 19:54
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 9 2008, 07:26
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



С использованием таблицы векторов прерываний идея понравилась.
Может быть и возможности компилятора (WinAVR/GCC) использовать по инициализации таблицы векторов ?
Типа:
Код
ISR(SIG_####)
{
  asm
  {
    pop
    pop
    jmp Get_version
  }
}

Правда, со стеком придется поизвращаться.
Или есть более прямой путь объяснить компилятору, чтобы он проинициализровал определенный вектор адресом произвольной функции ?

Сообщение отредактировал Огурцов - Sep 9 2008, 07:27
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 9 2008, 07:40
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 9 2008, 09:16
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 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 опять предусмотрена какая-нибудь хитрость(атрибут) ?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 9 2008, 09:50
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 9 2008, 13:26
Сообщение #7


Гуру
******

Группа: Участник
Сообщений: 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))
...


Ничего лучше пока не придумалось
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 10 2008, 06:42
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



Как вариант, использовать только первый вектор, в основном это SIG_INTERRUPT0, для получения адресов экспортируемых функций, либо всех сразу, либо по индексу.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 10 2008, 07:43
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 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)
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 10 2008, 08:06
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 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()

Согласен.

зы: хотя места в бут-секции мало и все нужные фичи уже не входятся.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Sep 10 2008, 08:30
Сообщение #11


Гуру
******

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



Цитата(Огурцов @ Sep 10 2008, 11:06) *
Вектор(ы) позволят организовать хоть какую-то совместимость приложений и загрузчиков.
Можно организовать подобие векторов по фиксированным адресам в конце загрузчика. Т.е. в конце загрузчика по фиксированным адресам разместить rjmp на эти функции. И адреса этих rjmp уже не менять. Остается только гарантировать, что при всех модификациях тип возвращаемых значений останется неизменным.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Огурцов
сообщение Sep 10 2008, 16:33
Сообщение #12


Гуру
******

Группа: Участник
Сообщений: 3 928
Регистрация: 28-03-07
Из: РФ
Пользователь №: 26 588



В общем, да, возможности те же, плюсы - вектор(ы) остаются свободны.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 22:30
Рейтинг@Mail.ru


Страница сгенерированна за 0.02723 секунд с 7
ELECTRONIX ©2004-2016