|
|
  |
Bootloader или загрузчик, расскажите по подробней... |
|
|
|
Apr 24 2009, 10:06
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Расскажите какие функции выполняет встроенный bootloader и как написать свой(и где он будет находиться). (ядро LPC2468/78)
З.Ы. когда на форумах вспоминуют про Bootloader и про загрузчик - то имеют ввиду одно и тоже?
Сообщение отредактировал Anatrulij - Apr 24 2009, 10:09
|
|
|
|
|
Apr 24 2009, 10:14
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Apr 24 2009, 13:06)  Расскажите какие функции выполняет встроенный bootloader и как написать свой(и где он будет находиться). (ядро LPC2468/78) Уйму раз на форуме писали. Например здесь и здесь. Пооиск - рулииит. Для google используйте тэг: Код site:electronix.ru Цитата З.Ы. когда на форумах вспоминуют про Bootloader и про загрузчик - то имеют ввиду одно и тоже? Да.
|
|
|
|
|
Apr 24 2009, 14:17
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
В данных ссылках я не увидел где конкретно находиться системный(или как он там называется) загружчик(по какому адресу) и как он влияет на работу программы(что он вообще делает, если я сам пишу загрузчик).
И провильно ли я понял: в самом начале я прошиваю программу(bootloader), а уже эта программа(если надо) по нужным адресам записывает другую программу(основную)?
|
|
|
|
|
Apr 24 2009, 14:52
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Apr 24 2009, 17:17)  В данных ссылках я не увидел где конкретно находиться системный(или как он там называется) загружчик(по какому адресу) и как он влияет на работу программы(что он вообще делает, если я сам пишу загрузчик). Где поместите, там и будет. Обычно в начале флеша. Практически - никак не влияет. Обычно загрузчик только обновляет основную программу. Загрузчик запускается по включению питания или по переходу из основной программы. Цитата И провильно ли я понял: в самом начале я прошиваю программу(bootloader), а уже эта программа(если надо) по нужным адресам записывает другую программу(основную)? Провильно. Впрочем, можно склеить их на этапе hex-файлов, и прошивать вместе (при первой прошивке пустого контроллера).
|
|
|
|
|
Apr 24 2009, 15:31
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Я под системным загрузчиком имел в виду загрузчик который идет вместе с контроллером - прошитый там навсегда(а может и нет)? Есть ли такой(где то здесь на форуме упоминали об таком)?
Сообщение отредактировал Anatrulij - Apr 24 2009, 16:01
|
|
|
|
|
Apr 24 2009, 21:26
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А по какому адресу он расположен, и какие его функции?
|
|
|
|
|
Apr 28 2009, 11:02
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
На этом этапе мне пока все понятно. Как я понял загрузчики - однотипные програмки.
Копнем теперь глубже - реализация загрузчика. Каким образом мне проверять есть ли во флеше рабочая прошивка?
|
|
|
|
|
Apr 28 2009, 11:42
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Из загрузчика я считаю контрольную сумму записанной во флеше программы, а потом сравниваю ее с контрольной суммой до этого посчитаную (и где-то записаной во флеше). Правильно ли я понял?
|
|
|
|
|
Apr 28 2009, 12:49
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
HARMHARM >> Да, конечно. Удобно положить контрольную сумму сразу после тела программы.
А от куда загрузчик знает где конец программы?
|
|
|
|
|
Apr 28 2009, 16:48
|

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

|
Цитата(Anatrulij @ Apr 28 2009, 15:49)  А от куда загрузчик знает где конец программы? Есть несколько путей: 1) Он может считать контрольную сумму всей доступной приложению памяти. В последней ячейке будет контрольная сумма. 2) В приложении по заранее оговоренному адресу хранится его размер.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Apr 29 2009, 13:07
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А где в стартапе указано адрес начала программы, адрес начала бутлоадера? я нашел вот такой код: Код Vectors LDR PC, Reset_Addr LDR PC, Undef_Addr LDR PC, SWI_Addr LDR PC, PAbt_Addr LDR PC, DAbt_Addr NOP ; Reserved Vector ; LDR PC, IRQ_Addr LDR PC, [PC, #-0x0120] ; Vector from VicVectAddr LDR PC, FIQ_Addr
Reset_Addr DCD Reset_Handler Undef_Addr DCD Undef_Handler SWI_Addr DCD SWI_Handler PAbt_Addr DCD PAbt_Handler DAbt_Addr DCD DAbt_Handler DCD 0 ; Reserved Address IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler SWI_Handler B SWI_Handler PAbt_Handler B PAbt_Handler DAbt_Handler B DAbt_Handler IRQ_Handler B IRQ_Handler FIQ_Handler B FIQ_Handler но ни где больше переменные не упоминаються(то есть нет присвоения им каких-либо значений) З.Ы. а есть описание кода в стартапе или описание того, как грамотно сделать стартап?
Причина редактирования: Оформление цитаты исходника.
|
|
|
|
|
Apr 29 2009, 13:21
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Apr 29 2009, 16:07)  А где в стартапе указано адрес начала программы, адрес начала бутлоадера? З.Ы. а есть описание кода в стартапе или описание того, как грамотно сделать стартап? В стартапе указан адрес инструкции, которую станет выполнять микроконтроллер. А у что там будет - бутлоадер или приложение - решать вам. Это: Код Vectors LDR PC, Reset_Addr первая инструкция, которую выполнит контроллер. Загрузка из Reset_Addr значения Reset_Handler в счетчик команд, по сути безусловный переход. Vectors это просто метка. Это: Код Reset_Addr DCD Reset_Handler Описание входной точки программы. Reset_Handler подставит линкер при сборке. Reset_Addr это метка. Инструкции как таковой я не видел. Хорошо сделаный стартап выкладывал Zltigo здесь. Правда, там много и того, что для вас будет лишним пока.
|
|
|
|
|
Apr 29 2009, 13:57
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А линкер это тоже отдельный фалик прикрученный к проекту?
|
|
|
|
|
Apr 29 2009, 14:15
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
я пишу на Keil
|
|
|
|
|
Apr 30 2009, 05:41
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
defunct>>для RVDS компилятора - см scatter file (.sct)
Смотрел я этот файл. вот его содержание:
LR_IROM1 0x00000000 0x00080000 { ; load region size_region ER_IROM1 0x00000000 0x00080000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x40000000 0x00010000 { ; RW data .ANY (+RW +ZI) } }
ER_IROM1 0x00000000 0x00080000 - значит что с адреса 0x00080000 начинается выполнение моей программи?
А где написано чему равна переменная Reset_Addr?
Сообщение отредактировал Anatrulij - Apr 30 2009, 05:49
|
|
|
|
|
Apr 30 2009, 06:01
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(sergeeff @ Apr 30 2009, 08:55)  Вообще полезно для начала детально изучить startup файл на предмет того, как он устроен. Вот я и начал детально изучать startup файл
|
|
|
|
|
Apr 30 2009, 09:24
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Что-то я не могу найти в Кейле, где указывается с какого адреса начинается моя программа.
|
|
|
|
|
Apr 30 2009, 11:42
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А где в scatter file указан адрес начала программи
|
|
|
|
|
Apr 30 2009, 14:12
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Apr 30 2009, 14:42)  А где в scatter file указан адрес начала программи Я мало понимаю в Keil, но кажется что строка Код ER_IROM1 0x00000000 0x00080000 указывает что линкер может разместить программу в этом диапазоне... Скорее всего с адреса 0 и разместит. Если хотите знать точно - смотрите в лог линкера.
|
|
|
|
|
Apr 30 2009, 14:33
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А как с бутлоадера передать управление на загруженную программу, а с программы (по необходимости) назад на бутлоадер?
|
|
|
|
|
Apr 30 2009, 18:49
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Apr 30 2009, 17:33)  А как с бутлоадера передать управление на загруженную программу, а с программы (по необходимости) назад на бутлоадер? С бутоладера - примерно так: Код extern __noreturn void switch_to_application(); ClearWDT(); __disable_interrupt(); switch_to_application(); При этом в ключах линкера объявлен символ (для IAR): Код -Dswitch_to_application=00018010 Естественно, есть соглашение (моё с самим собой), что по адресу 0х00018010 находится точка входа в приложение. Из приложения в бутлоадер тоже можно так делать, но я предпочитаю отравить внутренний watchdog неправильной последовательностью.
|
|
|
|
|
May 1 2009, 07:32
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
А для Keil?
|
|
|
|
|
May 1 2009, 10:15
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(Anatrulij @ May 1 2009, 10:32)  А для Keil? Не надо придумывать себе проблемы там, где их нет. В любом С компиляторе: Код typedef void (*pt2Function)(void);
pt2Function BootCall = (pt2Function)0x1000; // адрес, куда надо перейти
BootCall(); // собственно переход
|
|
|
|
|
May 1 2009, 10:50
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
После окончания работы функции, куда передается управление, или можно указать адрес функции main загруженной бутлоадером основной программы? Тогда возникает еще вопрос - main начинается с первого байта прошивки?
|
|
|
|
|
May 1 2009, 11:11
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(Anatrulij @ May 1 2009, 13:50)  После окончания работы функции, куда передается управление, или можно указать адрес функции main загруженной бутлоадером основной программы? Тогда возникает еще вопрос - main начинается с первого байта прошивки? Вы продумайте организацию работы вашего устройства. Что и в каком порядке инициализируется. Чтобы нормально стартовала ваша прикладная программа, т.е. main() к моменту ее вызова надо, чтобы были инициализированы все необходимые hardware-устройства (по крайней мере так принято), инициализирован сегмент bss, может быть скопирован сегмент данных data из FLASH в RAM, вызваны конструкторы глобальных объектов (в случае использования С++), инициализирована таблица прерываний. Так что помозгуйте кто (bootloader или прикладная программа) что из этого списка и в какой последовательности инициализирует - и вперед.
|
|
|
|
|
May 2 2009, 11:25
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(sergeeff @ May 1 2009, 14:11)  Так что помозгуйте кто (bootloader или прикладная программа) что из этого списка и в какой последовательности инициализирует - и вперед. Сразу будет записываться бутлоадер, а он же, по необходимости, будет обновлять основную прошивку. я просто еще не знаю как это все правильно организовуется. Мне так и не ответили на вопрос: После окончания работы функции, куда передается управление, или можно указать адрес функции main загруженной бутлоадером основной программы? Тогда возникает еще вопрос - main начинается с первого байта прошивки?
|
|
|
|
|
May 2 2009, 11:53
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ May 2 2009, 14:25)  я просто еще не знаю как это все правильно организовуется. Есть несколько разных вариантов... Цитата Мне так и не ответили на вопрос: После окончания работы функции, куда передается управление, или можно указать адрес функции main загруженной бутлоадером основной программы? Тогда возникает еще вопрос - main начинается с первого байта прошивки? Работы какой функции? Можно указать на main основной программы, если вы решили проводить всю инициализацию в загрузчике, и не используете C++. main начнется там, где его расположит линкер. Можно в принципе расположить main с первого байта прошивки, однако обычно в начале прошивки лежит её описание и векторы точек входа. То есть напрмер версия прошивки, длина прошивки, потом точки входа в приложение, в SWI, в FIQ, еще куда-нибудь.
|
|
|
|
|
May 2 2009, 12:10
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(HARMHARM @ May 2 2009, 14:53)  Есть несколько разных вариантов... Можете описать данные варианты. Если есть примерчик, выложите пожалуйста.
|
|
|
|
|
May 4 2009, 11:38
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Спасибо за ссылку. Сложновато пока для меня. может у кого то есть по проще? или где-то по этапам расписано, что и как делать.
|
|
|
|
|
May 4 2009, 12:08
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(zltigo @ May 4 2009, 14:48)  Значит так. Для начала Вы пропустили самый первый этап - нужно хоть чего-то достичь относительно самостоятельно. Например, написать моргающий светодиод и уж точно самостоятельно досконально разобраться как это и комплятор работают. Мигание светодиодом - это уже пройденный этам. Щас поставил перед собой задачу - написать бутлоадер, который прошивает во флеш основную программу через CAN. С чем разобрался: могу писать во флеш посредством IAP(с разположением секторов и прочее - понятно), с СAN-ном тоже знаком не плохо. Решил, что бутлоадер будет разположен в нулевом (если не хватит, то и в первом) секотрах. При старет будет проверяться есть ли рабочая прошивка, если есть - то прыгаем на нее, в противном случае ждем данных с CAN. По каманде из основной прошивки можно пригнуть на бутлоадер. Так же будет несколько команд по которым будет возвращаться номер прошивки и прочие нужные мне данные - Вот не знаю пока как это все реализовать, с чего начать???
|
|
|
|
|
May 7 2009, 11:38
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(sergeeff @ May 7 2009, 11:53)  Никак не могу понять, что же вам не понятно? Сами же все внятно описали, где-что будет лежать и что должно делать. Ну так и реализовывайте! я как раз не знаю как это реализовать
|
|
|
|
|
May 7 2009, 19:34
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(sergeeff @ May 7 2009, 21:01)  Для начала, считайте, что у вас пока одна единственная задача, имеющая собственный main(). У этой задачи есть low_level_init() - инициализация необходимого по-минимуму железа (CAN, в частности) и в main() - какой-нибудь "Hello world". Все это должно лежать в нулевом секторе flash. Когда все это заработает - это 80% успеха. Ок. Спасибо.
|
|
|
|
|
May 8 2009, 07:34
|

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

|
Цитата(Anatrulij @ May 7 2009, 14:38)  я как раз не знаю как это реализовать Посмотрите, как это реализовывали до вас. Вот, например, AVR231:AES Bootloader. Да, он для совершенно другого процессора, но описание достаточно подробное, а в С-коде разобраться нетрудно.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jun 12 2009, 07:32
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Был отвлечен другим делом, теперь можно вернуться к загузчику. Цитата(Сергей Борщ @ May 8 2009, 10:34)  Посмотрите, как это реализовывали до вас. Вот, например, AVR231:AES Bootloader. Да, он для совершенно другого процессора, но описание достаточно подробное, а в С-коде разобраться нетрудно. Спасибо за ссылку. Посмотрел. Логику бутлоадера я понял, теперь дело в реализации, но еще не до конца понял как передается управление на основную(прошитую) программу
|
|
|
|
|
Jun 12 2009, 08:35
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
В IAP указано что можно писать до 4kB, а как быть с секторами которые "важут" 32kB?
|
|
|
|
|
Jun 12 2009, 11:08
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(SasaVitebsk @ Jun 12 2009, 13:54)  Не совсем понятно о чём вы. Если про запись блоками по 32кб, то набираете эти 32к мелкими блоками и записываете. Извените, если не правельно задал вопрос - переформирую его. в команде записи во флеш указываешь в какой сектор и сколько писать, так как размер 10 - 21 секторов 31кБ, а в команде можно указать не более 4 кБ, как мне записать остальные данные в этот сектор.
Сообщение отредактировал Anatrulij - Jun 12 2009, 11:09
|
|
|
|
|
Jun 13 2009, 11:26
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(HARMHARM @ Jun 13 2009, 09:08)  Сектор надо стереть (очищается целиком), да и вообще размер сектора - это к стиранию относится. Записывать любыми кусками, но каждый кусок не более одного раза. То есть запишете 8 раз блок по 4кб. Если я правельно понял - то получается следующее: 1. стерли 10-й сектор 2. при записи указали 10 сектор и записать 256 байт 3.если мы сново укажим 10 сектор для записи, то сектор начьнет записываться начиная с 257-го байта????
Сообщение отредактировал Anatrulij - Jun 13 2009, 11:29
|
|
|
|
|
Jun 13 2009, 12:08
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Jun 13 2009, 14:26)  Если я правельно понял - то получается следующее: 1. стерли 10-й сектор 2. при записи указали 10 сектор и записать 256 байт 3.если мы сново укажим 10 сектор для записи, то сектор начьнет записываться начиная с 257-го байта???? Нет, нет. Читайте же документацию! Секторами происходит только стирание! Параметр команды 51: Цитата Destination flash address where data bytes are to be written. This address should be a 256 byte boundary.
|
|
|
|
|
Jun 13 2009, 13:28
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(HARMHARM @ Jun 13 2009, 15:08)  Нет, нет. Читайте же документацию! Секторами происходит только стирание! Параметр команды 51: Тоесть, можно свободно указывать не сектор, а адрес, но адрес должен быть кратным 256??? З.Ы. Блин, сижу теперь и думаю: "кто меня на вел на мысль, что записывать нужно только секторами  "
Сообщение отредактировал Anatrulij - Jun 13 2009, 13:30
|
|
|
|
|
Jun 17 2009, 07:42
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Во флеш хочу писать блоками по 4кБ, для этого мне нужно сначала данные писать в RAM. Здесь было сказано, что "в 99,9999% запись по конкретным адресам RAM совершенно неразумное решение" - zltigo. Еще я хотел создать массив на такой же размер(буффер), а потом скидывать в RAM и использовать команду Copy RAM to Flash, но массив тоже хранится в ОЗУ. Они не затрут друг-друга. Как мне быть в этой ситуации?
Сообщение отредактировал Anatrulij - Jun 17 2009, 07:56
|
|
|
|
|
Jun 17 2009, 08:37
|

читатель даташитов
   
Группа: Свой
Сообщений: 853
Регистрация: 5-11-06
Из: Днепропетровск
Пользователь №: 21 999

|
Цитата(Anatrulij @ Jun 17 2009, 10:42)  Во флеш хочу писать блоками по 4кБ, для этого мне нужно сначала данные писать в RAM. Здесь было сказано, что "в 99,9999% запись по конкретным адресам RAM совершенно неразумное решение" - zltigo. ИМХО Zltigo имел в виду, что нужно пользоваться типами, а не лезть в память по адресам. Это к Вашей программе не отностится. Надеюсь. Цитата Еще я хотел создать массив на такой же размер(буффер), а потом скидывать в RAM и использовать команду Copy RAM to Flash, но массив тоже хранится в ОЗУ. Они не затрут друг-друга. Именно так - создаёте массив на 4 КБ с выравниванием 4, потом делаете Copy RAM to Flash.
|
|
|
|
|
Jun 17 2009, 08:40
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(HARMHARM @ Jun 17 2009, 11:37)  Именно так - создаёте массив на 4 КБ с выравниванием 4, потом делаете Copy RAM to Flash. Что значит выравнивание 4?
|
|
|
|
|
Jun 17 2009, 14:50
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Anatrulij @ Jun 17 2009, 10:42)  Как мне быть в этой ситуации? Не писать по конкретным адресам  . На все есть переменные, массивы, менеджеры памяти, сегменты линковочные,... Они и только должны знать о конкретных адресах ЗАПРОШЕННОЙ Вами памяти. Вы пользуетесь только именами обьектов. Опишите, спросите, получите, пользуйтесь. Все. Цитата(Anatrulij @ Jun 17 2009, 11:40)  Что значит выравнивание 4? Скорее всего для Вас пока ничего - "само" получится.
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 17 2009, 19:01
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(zltigo @ Jun 17 2009, 17:50)  Не писать по конкретным адресам  . Я бы с радостью  , но при работе с флеш этого не избежать. Сначала я данные пишу в RAM по конкретному адресу, а потом этот адрес скармливаю команде 51. Так что, затру ли я свой 4кБ-вый массив данными которые буду писать в RAM для оправки во флеш???
Сообщение отредактировал Anatrulij - Jun 17 2009, 19:10
|
|
|
|
|
Jun 17 2009, 21:22
|

Гуру
     
Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244

|
Цитата(Anatrulij @ Jun 17 2009, 22:01)  Я бы с радостью  , но при работе с флеш этого не избежать. Работа с флешью или не с чем-то другим ну никак не относится к делу. Цитата Сначала я данные пишу в RAM Да Цитата по конкретному адресу, Зачем? Чем '0x12345678' привлекательнее 'buffer' Цитата а потом этот адрес скармливаю команде 51. Без проблем. Цитата Так что, затру ли я свой 4кБ-вый массив данными которые буду писать в RAM для оправки во флеш???  Если я брошу куда-нибудь кирпич, то я чего-нибудь сломаю???
--------------------
Feci, quod potui, faciant meliora potentes
|
|
|
|
|
Jun 18 2009, 05:47
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(zltigo @ Jun 18 2009, 00:22)  Зачем? Чем '0x12345678' привлекательнее 'buffer' Ух ты!!!! Вроде я уследил за ходом выших мыслей... Я создаю массив buffer[4096], забиваю его данными, а потом в команде 51 просто указываю имя массива buffer(имя является адресом первого элемента). правильно ли я понял????
|
|
|
|
|
Jun 23 2009, 12:51
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Ложу я прошивку с помощью бутлоадера(сам он находиться по 0-му адресу) по адресу 0х00004000 проверяю целостность и прочее - все Ок. передаю управление на прошивку вот так:
typedef void (*pt2Function)(void);
pt2Function BootCall = (pt2Function)0x00004000;
в итоге - ничего. он все равно крутится в бутлоадере.
может я не правельно передаю управление???
|
|
|
|
|
Jun 24 2009, 06:19
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(Anatrulij @ Jun 23 2009, 15:51)  может я не правельно передаю управление??? Утро вечера мудренее  . Разобрался - надо было перед вызовом вышеописанного перехода сбросить все альтернативные функции портов. Но я не знаю почему данная процедура помогла.
|
|
|
|
|
Jun 24 2009, 07:29
|
Гуру
     
Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48

|
Вот только перейдете вы по этому адресу в user-mode процессора и перенастроить стеки для других режимов уже не сможете. Поэтому лучше вызывать вот такую функцию (для KEIL): Код /* Функция передачи управления пользовательской программе по адресу 0x2000 */ void __asm user(void) { ARM mov r0, #0x00002000 swi 0 } в проект добавить файл swi.s Код PRESERVE8 AREA SWI_Area, CODE, READONLY ARM
EXPORT SWI_Handler SWI_Handler BX R0 END и конечно в startup.s сделать импорт SWI_Handler Код IMPORT SWI_Handler Reset_Addr DCD Reset_Handler Undef_Addr DCD Undef_Handler SWI_Addr DCD SWI_Handler PAbt_Addr DCD PAbt_Handler DAbt_Addr DCD DAbt_Handler DCD 0 ; Reserved Address IRQ_Addr DCD IRQ_Handler FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler ;SWI_Handler B SWI_Handler PAbt_Handler B PAbt_Handler DAbt_Handler B DAbt_Handler IRQ_Handler B IRQ_Handler FIQ_Handler B FIQ_Handler
--------------------
Вам помочь или не мешать?
|
|
|
|
|
Jun 24 2009, 07:53
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(Nixon @ Jun 24 2009, 10:29)  Вот только перейдете вы по этому адресу в user-mode процессора и перенастроить стеки для других режимов уже не сможете. Поэтому лучше вызывать вот такую функцию (для KEIL): Спасибо за совет. А можно более подробно прокоментировать код?
|
|
|
|
|
Jun 24 2009, 10:12
|
Участник

Группа: Новичок
Сообщений: 64
Регистрация: 7-11-08
Пользователь №: 41 437

|
Цитата(Nixon @ Jun 24 2009, 12:13)  Что именно тут комментировать? Вы вызываете SWI прерывание, при вызове которого переключается режим cpu на supervisor и на всякий случай в ARM. И уже в этом режиме вы переходите на адрес пользовательской программы (адрес передается в r0). а зачем делать импорт SWI_Handler. многого я еще не знаю и что бы не задавать глупых вопросов, ткните где я могу найти описания того как правельно инициализировать контроллер, вектора и прочее.
|
|
|
|
|
Jun 30 2010, 14:32
|
Частый гость
 
Группа: Свой
Сообщений: 187
Регистрация: 22-06-05
Из: Минск, Беларусь
Пользователь №: 6 213

|
Для организации загрузки программы написал несколько классов, которые должны использоваться в бутлоадере (AES шифрование, подсчет CRC и т.д.). Написал собственно загрузчик, но теперь осталось правильно все это скомпоновать.
Как сделать, чтобы определенные объекты классов компилировались с 0-го сектора (загрузчик), а остальные скажем со 2-го сектора (пользовательская программа)?
Вычитал, что это решается с помощью scatter, нашел где он настраивается в Keil, но там вроде можно всю программу сместить, а как сделать частями, ума не приложу. Была идея сделать 2 разных проекта, один загрузчик и разместить его с 0-го сектора (и использовать далее во всех остальных проектах его без изменения). А второй проект это пользовательская программа, которая всегда начинается со 2-го сектора. Есть еще плюсы, у этого метода, но главные минусы в том, что: - всегда надо четко и, самое главное, в ручную оговаривать точки входа в пользовательскую программу (включая вектора прерываний) и загрузчик, потому что при компиляции они не будут знать о существовании друг друга; - хотелось быть часть однотипного кода по работе с интерфейсами, USB, CAN и UART разместить в загрузчике, чтобы не дублировать их в двух программах. Но тут встает та же проблема, ручного указания адресов методов и самое главное ручное резервирование памяти, которое используют объекты классов интерфейсов, чтобы компилятор пользовательской программы туда ничего не назначил.
|
|
|
|
|
Jun 30 2010, 15:52
|

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

|
Цитата(Yaumen @ Jun 30 2010, 17:32)  Была идея сделать 2 разных проекта, один загрузчик и разместить его с 0-го сектора (и использовать далее во всех остальных проектах его без изменения). А второй проект это пользовательская программа, которая всегда начинается со 2-го сектора. Правильное решение. Программы независимы, нет возможности развивая программу случайно сделать ее несовместимой с уже выпущенными и разлетевшимися по стране загрузчиками. Цитата(Yaumen @ Jun 30 2010, 17:32)  - всегда надо четко и, самое главное, в ручную оговаривать точки входа в пользовательскую программу (включая вектора прерываний) и загрузчик, потому что при компиляции они не будут знать о существовании друг друга; Вход в загрузчик - по адресу 0. В приложение (после ремапа) - тоже по адресу 0. Адрес фиксирован, не меняется. Цитата(Yaumen @ Jun 30 2010, 17:32)  - хотелось быть часть однотипного кода по работе с интерфейсами, USB, CAN и UART разместить в загрузчике, чтобы не дублировать их в двух программах. Но тут встает та же проблема, ручного указания адресов методов сделайте таблицу переходов, расположите ее раз и навсегда в фиксированном месте. Цитата(Yaumen @ Jun 30 2010, 17:32)  и самое главное ручное резервирование памяти, которое используют объекты классов интерфейсов, чтобы компилятор пользовательской программы туда ничего не назначил. Расположите их в начале ОЗУ, сразу за отремапленой таблицей векторов. А приложению уменьшите количество ОЗУ на этот размер. Но это тоже не лучшее решение - а найдете вы потом (через год) багу в этом коде, которая не мешает загрузчику, но не дает работать приложению. И что - отзывать все выпущенные приборы на перешивку загрузчика? Или писать очередное обновление, которое перепишет загрузчик с ненулевой вероятностью сбоя питания в этот момент и все - устройство надо возвращать. Пусть лучше дублируются, но загрузчик и приложение будут совершенно автономны.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 1 2010, 03:21
|

Участник

Группа: Участник
Сообщений: 67
Регистрация: 8-05-09
Из: Томск
Пользователь №: 48 809

|
Цитата(Сергей Борщ @ Jun 30 2010, 22:52)  сделайте таблицу переходов, расположите ее раз и навсегда в фиксированном месте. Можно с этого места поподробнее?  Т.е. саму идею понял, но как это все должно выглядеть - не совсем
|
|
|
|
|
Jul 1 2010, 05:30
|
Частый гость
 
Группа: Свой
Сообщений: 187
Регистрация: 22-06-05
Из: Минск, Беларусь
Пользователь №: 6 213

|
Цитата(Сергей Борщ @ Jun 30 2010, 18:52)  Вход в загрузчик - по адресу 0. В приложение (после ремапа) - тоже по адресу 0. Адрес фиксирован, не меняется. Вот тут немного поподробнее. С загрузчиком все понятно, у него свой main(), который может располагаться где угодно в пределах первых 2-х секторов, а переход на main() действительно будет по 0-му адресу. Теперь о пользовательской программе. У него также main может располагаться в любом месте оставшейся памяти и об адресе этого main() загрузчик естественно ничего не знает. Значит ему надо это указать, опять же в пользовательской области зафиксировать переход на main(), по этому адресу и будет переходить загрузчик в случае, если с прошивкой все в норме. Возможно есть еще какой-то способ, но похоже я до него еще в голове не дошел. Есть еще один минус у двух проектов. Я планирую использовать AES шифрование, которое жестко будет зашито в загрузчик, а значит все пользовательские программы необходимо шифровать одним и тем же ключем, это же касается и сигнатуры. Мне кажется это неправильно!!! Теперь что касается общей части для обоих проектов. Смысл идеи состоит в том, чтобы дать возможность обновлять прошивку удаленно. В моем случае это происходит через штатно установленный отдельный модуль связи, который общается с другими модулями по CAN. Для работы на этой шине, разработан протокол обмена, позволяющий передавать файлы больших размеров, склеивать их на приемном устройстве, вести одновременный прием от нескольких устройств, ну и т.д. Это достаточно большой кусок куда, который не хотелось бы дублировать, чтобы не тратить лишнего, так как я и так уже вышел на использование 75% имеющейся памяти. А в добавок, этот фрагмент кода очень емкий по использованию RAM. Мне самому идея удаленного программирования не нравится, однако начальство настаивает на его присутствии, так как у нас уже были случаи, когда приходилось объезжать множество объектов для перепрошивки, а когда эти объекты находятся в разных городах или даже в странах это еще более утомительно.
|
|
|
|
|
Jul 1 2010, 09:40
|

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

|
Цитата(alvy @ Jul 1 2010, 06:21)  Можно с этого места поподробнее?  Т.е. саму идею понял, но как это все должно выглядеть - не совсем для gcc примерно так: Код boot_app_cross_table.h: struct boot_app_cross_table { uint32_t (*Serial_no)(); void (*AES_init)(uint32_t *init_vector); void (*AES_decode)(uint32_t *block); bool (*TCP_send)(void const * from, size_t size); }extern Bootloader;
//========= bootloader.cpp:
extern uint32_t Serial_no(); void AES_init(uint32_t * init_vector) { AES.init(init_vector); }
void AES_decode(uint32_t * block) { AES.decode(block); } extern void TCP_send(void const * from, size_t size);
__attribute__((section, ".boot_app_cross")) Bootloader = { Serial_no, AES_init, AES_decode, TCP_send, };
//========= bootloader.ld: MEMORY { ..... CROSS (rx) : ORIGIN = 0x00100040, LENGTH = 4 * 4 .... }
SECTIONS { ..... .cross : { KEEP(*(.boot_app_cross*)) } > CROSS
//========= application.cpp: #include "boot_app_cross_table" void Test() { printf("Serial number: %d", Bootloader.Serial_no()); }
//========= makefile: LDFLAGS += -Wl,--defsym,Bootloader=0x00100040 Цитата(Yaumen @ Jul 1 2010, 08:30)  Вот тут немного поподробнее. С загрузчиком все понятно, у него свой main(), который может располагаться где угодно в пределах первых 2-х секторов, а переход на main() действительно будет по 0-му адресу. До main() еще дойти надо. До вызова main() исполняется startup-код, который готовит переменные, настраивает стеки и кое-какую периферию, вызывает конструкторы глобальных объектов и уже после всего этого вызывает main(). А сам стартап-код вызывается из вектора исключения RESET. Цитата(Yaumen @ Jul 1 2010, 08:30)  Теперь о пользовательской программе. У него также main может располагаться в любом месте оставшейся памяти и об адресе этого main() загрузчик естественно ничего не знает. У приложения точно так-же есть своя таблица векторов. В которой вектор RESET указывает на стартап-код. А стартап-код вызывает main(). Загрузчик копирует эту таблицу в начало ОЗУ и делает remap. Таблица оказывается отражена на адрес 0. По адресу 0 оказывается команда перехода на стартап-код приложения. Осталось перейти на адрес 0. Цитата(Yaumen @ Jul 1 2010, 08:30)  Есть еще один минус у двух проектов. Я планирую использовать AES шифрование, которое жестко будет зашито в загрузчик, а значит все пользовательские программы необходимо шифровать одним и тем же ключем, это же касается и сигнатуры. Мне кажется это неправильно!!! Почему? А если все программы будут с разными ключами - как вы их загрузите в одно устройство? Цитата(Yaumen @ Jul 1 2010, 08:30)  разработан протокол обмена, позволяющий передавать файлы больших размеров, склеивать их на приемном устройстве, вести одновременный прием от нескольких устройств, ну и т.д. Это достаточно большой кусок куда, который не хотелось бы дублировать Нужна ли вся эта функциональность загрузчику? Может ему достаточно сильно урезанной версии? Или может у приложения есть возможность сохранить образ прошивки в какой-то внешней памяти, а загрузчик тогда будет брать шифрованную прошивку из этой памяти? А как аварийный вариант и для первоначальной загрузки предусмотреть что-нибудь типа uart?
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Jul 1 2010, 10:56
|
Частый гость
 
Группа: Свой
Сообщений: 187
Регистрация: 22-06-05
Из: Минск, Беларусь
Пользователь №: 6 213

|
Цитата(Сергей Борщ @ Jul 1 2010, 12:40)  Почему? А если все программы будут с разными ключами - как вы их загрузите в одно устройство? Имелось в виду, что создавая загрузчик как отдельный проект я его буду зашивать во все свои устройства, а это могут быть совершенно разные устройства и модули Цитата Нужна ли вся эта функциональность загрузчику? Может ему достаточно сильно урезанной версии? Или может у приложения есть возможность сохранить образ прошивки в какой-то внешней памяти, а загрузчик тогда будет брать шифрованную прошивку из этой памяти? А как аварийный вариант и для первоначальной загрузки предусмотреть что-нибудь типа uart? Если бы в микроконтроллерах RAMа было бы больше ROMa, то можно было бы использовать RAM как временный буфер, но увы это не так. А случись что во время программирования, то и вообще этот механизм накрывается медным тазом.
|
|
|
|
|
Jul 1 2010, 12:20
|
Частый гость
 
Группа: Свой
Сообщений: 187
Регистрация: 22-06-05
Из: Минск, Беларусь
Пользователь №: 6 213

|
Цитата(Сергей Борщ @ Jul 1 2010, 14:35)  Так что мешает при компиляции под конкретный модуль подставлять заголовочный файл с ключами шифрования для этого конкретного устройства. Или просто держать копию исходников загрузчика в папке с проектом конкретного модуля (у меня так). Т.е., хоть у Вас бутлоадер это отдельный проект, он все равно уникален с точки зрения для какого устройства он компилируется. Так?
|
|
|
|
|
  |
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|