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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Опять про загрузчик..., Не получается передать управление.
amw
сообщение May 12 2008, 16:56
Сообщение #31


Знающий
****

Группа: Свой
Сообщений: 601
Регистрация: 22-09-05
Из: Kharkov
Пользователь №: 8 847



Цитата(user234 @ May 12 2008, 16:39) *
Спасибо.

???
Помогло? smile.gif

А что за компилятор?


--------------------
- А мораль отсюда такова: всякому овощу свое время. Или, хочешь, я это сформулирую попроще: никогда не думай, что ты иная, чем могла бы быть иначе, чем будучи иной в тех случаях, когда иначе нельзя не быть.
© Lewis Carroll. Alice's adventures in wonderland.
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 24 2008, 11:50
Сообщение #32


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Здравствуйте, уважаемые. Понимаю, что этот вопрос уже поднимался, но хотелось бы получить ответы конкретно по своей задаче.
Итак, был мною написан загрузчик для LPC2132, работающий по следующей схеме:
1. Проекты загрузчика и основной программы независимы
2. Для загрузчика определено адресное пространство во флэш:
-DROMSTART=01000
-DROMEND=05FFF
Жирность загрузчика определяется необходимостью поддержки части периферии, возможностью связи с внешним устройством и компом для получения прошивки основной программы и работы с AT45.

Для основной программы (ОП): [200-FFF],[6000-FFFF]
3. При получении прошивки ОП загрузчик проверяет её на валидность, делает подмену стартового адреса своим, сохраняет стартовый адрес ОП в резервной области LPC, корректирует CRC-векторов, записывает нулевую страницу, обходит "свою" область, записывает оставшуюся область ОП.
4. По окончании записи проверяет ОП во flash LPC на валидность, переходит на исполнение ОП.

Всё работает, работает замечательно, но, как можно заметить, необходимо стирать нулевой сектор, что приводит к возможному "слёту" прошивки при выключении питания/сбросе, если не успела записаться область 0x00-0x3F. Хотелось бы узнать пути решения этой проблемы: как вообще не трогать нулевой сектор? Т.е. адреса 0x0000-0x5FFF должны быть неприкосновенными.
Из форума видел пока только одно решение - ремапить в ОЗУ по адресам 0x00-0x3F область INTVEC основной программы. Но, судя опять же по форуму, это ненадёжно, т.к. существует риск затирания этой области некорректным исполнением кода основной программы. Есть ли возможность использования для основной программы векторов из flash, жертвуя использованием прерываний в загрузчике?

Сообщение отредактировал Altemir - May 24 2008, 12:31
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 24 2008, 13:45
Сообщение #33


Гуру
******

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



Цитата(Altemir @ May 24 2008, 14:50) *
Но, судя опять же по форуму, это ненадёжно, т.к. существует риск затирания этой области некорректным исполнением кода основной программы.
А если основная программа затрет не эту область, а, скажем 0x400000F0 - 0x40000100, то это будет способствовать повышению надежности? Включайте собаку, при слете она будет перезапускать проц, загрузчик будет восстанавливать вектора и так пока не найдете ошибку.

Давно использую вариант с ремапом на LPC2214 и AT91SAM7 - никаких нареканий. Нестирание нулевого сектора дает гарантию сохранение жизнеспособности при пропадании питания, сбросе, при обрыве связи в процессе перепрошивки, но никак не при ошибках в программе.


--------------------
На любой вопрос даю любой ответ
"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
Altemir
сообщение May 24 2008, 14:01
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Всё это понятно. Вы с Argon-ом на: Сахаре
обсуждали реализацию ремапа в ОЗУ, я это тоже изучил. Там же указывалось на возможность "задать фиксированное значение векторов" (с переходом на таблицу векторов ОП, к примеру 0x6000-0x603F) в бутлодыре для ОП, так, что прерывания будут исполняться на один переход больше. Такой вопрос не изучали?

Собака у меня всегда включена, а насчёт размещения векторов в ОЗУ здесь на форуме имеются как минимум два противника: zltigo и Kirill Frolov. Очень интересно и их выслушать.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 24 2008, 14:10
Сообщение #35


Гуру
******

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



Цитата(Altemir @ May 24 2008, 13:50) *
Есть ли возможность использования для основной программы векторов из flash, жертвуя использованием прерываний в загрузчике?

Ну зачем чем-то жертвовать, куда-то мапировать (жертвуя RAM), если банально перепрограммируется контроллер прерываний и все. А, exceptions handlers при этом всегда в загрузчике - так даже лучше.
Первые 0x40 байт загрузчика для LPC21/2xx:
Код
                ORG     0x00
__program_start:
                ldr     pc,(?vect_entry + 4*0) ; 00  Reset
                ldr     pc,(?vect_entry + 4*1) ; 04  UND
                ldr     pc,(?vect_entry + 4*2) ; 08  SWI
                ldr     pc,(?vect_entry + 4*3) ; 0C  P_ABT
                ldr     pc,(?vect_entry + 4*4) ; 10  D_ABT
                dc32    0                       ; 14 Summ of other vectors instructions
                ldr     pc, [pc,#-0xFF0]        ; 18 Jump directly to the address given by the AIC
                                                ; from [0xFFFFF030] Curent 18h +8(conveyer)=20h
                ldr     pc,(?vect_entry + 4*7) ; 1C  FRQ
;----------------------------------------------------------------------------
?vect_entry:
                dc32    ?cstartup              ; Reset
                dc32    ?undf_abort            ; UND
                dc32    (KERNEL_LOCATION+0x08) ; SWI
                dc32    ?pref_abort            ; P_ABT
                dc32    ?data_abort            ; D_ABT
                ldr     pc,(?vect_entry +4*6)  ; Entry Point from application
                dc32    ?entry_point           ;  ...
                dc32    (KERNEL_LOCATION+0x0C) ; FRQ  ( With offset in Kernel )


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 24 2008, 15:21
Сообщение #36


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Цитата(zltigo @ May 24 2008, 18:10) *
Ну зачем чем-то жертвовать, куда-то мапировать (жертвуя RAM), если банально перепрограммируется контроллер прерываний и все. А, exceptions handlers при этом всегда в загрузчике - так даже лучше.

Я, конечно, понимаю, что вы давно работаете в этой области и хорошо изучили данный вопрос, но всю силу ARM-ов мне пока не привелось познать. В текущем проекте основной программы я настраивал Vectored Interrupt Controller (VIC), например, так:
Код
//Vectored Interrupt Controller
    
    VICProtection=0x00;                         //No Protection
    VICIntSelect=0x00000000;                //All requests - IRQ
    VICSoftIntClear=0xFFFFFFFF;             //Release all software requests
    VICIntEnClear=0xFFFFFFFF;               //Disable all interrupts
    
    VICIntEnable=((1<<VIC_TIMER0)|        //Включить прерывание по TIMER0
    (1<<VIC_TIMER1)|                //Включить прерывание по TIMER1
    (1<<VIC_PWM0)|                //Включить прерывание по PWM0
    (1<<VIC_UART1));                //Включить прерывание по UART1
    
    
    VICVectAddr0=(DWORD)&Timer0_Int;                //Priority 0 - TIMER0
    VICVectCntl0=0x20|VIC_TIMER0;
    VICVectAddr1=(DWORD)&Timer1_Int;                //Priority 1 - TIMER1
    VICVectCntl1=0x20|VIC_TIMER1;
    VICVectAddr2=(DWORD)&PWM0_Int;        //Priority 2 - PWM0
    VICVectCntl2=0x20|VIC_PWM0;
    VICVectAddr3=(DWORD)&Uart1_Int;        //Priority 3 - UART1
    VICVectCntl3=0x20|VIC_UART1;
    
    VICVectAddr=0;                              //Clear one interrupt


Я понимаю, что векторов 16 и при переинициализации VIC их может использовать, к примеру, загрузчик, но при этом пока не понимаю как соотносить адреса 0x00-0x3F для основной программы и загрузчика. И где это указывать?

Спасибо за терпение.

P.S. Похоже, пока я отвечал, вы добавили код, изучаю...

zltigo
Как я понял:
1. KERNEL_LOCATION - адрес основной программы (ОП)
2. ?cstartup - загрузчик
3. Производится разделение прерываний для ОП и загрузчика. В моём случае хочу так: IRQ - для ОП, FIQ - для загрузчика
4. При инициализации VIC-а в загрузчике: VICIntSelect=0xFFFFFFFF, в ОП: VICIntSelect=0x00000000
5. В итоге - задействую всего 3 адреса в пространстве 0x00-0x3F:
0x0000 0000 Reset
0x0000 0018 IRQ
0x0000 001C FIQ

Я всё правильно понял? Тогда я должен прописать в *.xcl-файле IARа для основной программы -Z(CODE)INTVEC=00-3F и поскольку адрес основной программы предопределён, то никаких последующих изменений и подмен адресов не потребуется?

Сообщение отредактировал Altemir - May 24 2008, 14:28
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 24 2008, 16:21
Сообщение #37


Гуру
******

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



Цитата(Altemir @ May 24 2008, 17:21) *
3. Производится разделение прерываний для ОП и загрузчика.

Нет.
Читаем комментарий: IRQ "Jump directly to the address given by the AIC"
Для FIQ, можно аналогично, но у меня он прямо в приложение направляется.
Если что не понятно, то читаем описание VIC, для углубленного изучения можно зайти на сайт ARM - там есть более подробные описания, нежели от производителей их чипов.
...
И на все последующие вопросы - нет sad.gif


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 24 2008, 17:01
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Цитата
Нет.
Читаем комментарий: IRQ "Jump directly to the address given by the AIC"

И как определить этот адрес? В бинарнике основной программы он постоянно меняется при её изменении. В LPC есть VIC и даже в оригинальных от arm.com не нашёл AIC sad.gif Не понимаю совершенно, КАК вы разделяли прерывания для основной программы и загрузчика. Везде в форуме написано, что вы это сделали, но нигде не описано, как это повторить и как настраивать прерывания для загрузчика и ОП при этом unsure.gif

Опытным путём удалось установить, что по адресу 0x38 расположен адрес моей функции:
Код
//IRQ exception handler
#pragma vector=0x18
__irq __arm void irq_handler(void)
{
    ((void(*)())VICVectAddr)();     //Call function on vector
    VICVectAddr = 0;                //Clear interrupt in VIC
}

Но как задать этой функции предопределённый адрес во флэш тогда? Обычным @0x6200 не получается, компилер ругается

Цитата
Для FIQ, можно аналогично, но у меня он прямо в приложение направляется.

В какое и как?

Цитата
Если что не понятно, то читаем описание VIC, для углубленного изучения можно зайти на сайт ARM - там есть более подробные описания, нежели от производителей их чипов.

Документ не намного подробнее от NXP sad.gif

Цитата
И на все последующие вопросы - нет sad.gif

Я в отчаянии...

Сообщение отредактировал Altemir - May 24 2008, 17:13
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 24 2008, 17:51
Сообщение #39


Гуру
******

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



Цитата(Altemir @ May 24 2008, 19:01) *
Везде в форуме написано, что вы это сделали, но нигде не описано, как это повторить

Я фигею - в этой теме уже писал:
Код
                ldr     pc, [pc,#-0xFF0]      ; 18 Jump directly to the address given by the AIC

Цитата
и как настраивать прерывания для загрузчика и ОП при этом unsure.gif

А вот так - Вас цитирую:
Код
VICVectAddr0=(DWORD)&Timer0_Int;                //Priority 0 - TIMER0
    VICVectCntl0=0x20|VIC_TIMER0;
    VICVectAddr1=(DWORD)&Timer1_Int;                //Priority 1 - TIMER1
    VICVectCntl1=0x20|VIC_TIMER1;
    VICVectAddr2=(DWORD)&PWM0_Int;        //Priority 2 - PWM0
    VICVectCntl2=0x20|VIC_PWM0;
    VICVectAddr3=(DWORD)&Uart1_Int;        //Priority 3 - UART1
    VICVectCntl3=0x20|VIC_UART1;

Причем процедура ОДИНАКОВА, для обоих.

Что тут можно не понять?


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 24 2008, 18:06
Сообщение #40


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Цитата(zltigo @ May 24 2008, 21:51) *
Что тут можно не понять?

Можно тут не понять то, как, имея одно и то же значение по адресу 0x38 проц определит, куда ему переходить на обработку прерывания, но, похоже, догоняю:
1. Приведённый мной irq_handler() для обработки прерывания использует адрес фунции, хранимой в слоте VICVectAddr0-15
2. Поскольку слоты настраиваются для загрузчика и ОП по-своему, то и переход будет именно на те функции, которые актуальны
3. Описанная в основной программе функция irq_handler() использоваться не будет, т.к. её заменяет функция irq_handler() бутлоадера (точнее, по адресу 0x38 будет находиться именно вызов хэндлера загрузчика)

Теперь всё так?

P.S. И ещё, при указании в *.xcl-файле ОП:
-DROMSTART=06000
-DROMEND=0FFFF
по адресу 0x20 лежит значение не 0x6000, а 0x603C. С чем это связано? Чем заняты адреса 0x6000-0x603B? Как корректно предопределить адрес ОП?

Сообщение отредактировал Altemir - May 24 2008, 18:49
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 24 2008, 19:38
Сообщение #41


Гуру
******

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



Цитата(Altemir @ May 24 2008, 21:06) *
3. Описанная в основной программе функция irq_handler() использоваться не будет, т.к. её заменяет функция irq_handler() бутлоадера (точнее, по адресу 0x38 будет находиться именно вызов хэндлера загрузчика)

Теперь всё так?
Нет. Не так. Весь irq_handler() уже есть. Он один единственный и прибит гвозьдями на вектор прерывания. Вот он:
Код
            ldr     pc, [pc,#-0xFF0]     ; 18 Jump directly to the address given by the AIC
Оно вызывает нужный из ваших Timer1_Int, PWM0_Int и т.д. Кто из них в данный момент нужен - он узнает из регистра [pc,#-0xFF0]. Подробности об этом регистре - в документации. Это регистр VICVectAddr.


--------------------
На любой вопрос даю любой ответ
"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
Altemir
сообщение May 24 2008, 19:53
Сообщение #42


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Цитата(Сергей Борщ @ May 24 2008, 23:38) *
Нет. Не так. Весь irq_handler() уже есть. Он один единственный и прибит гвозьдями на вектор прерывания. Вот он:
Код
            ldr     pc, [pc,#-0xFF0]    ; 18 Jump directly to the address given by the AIC
Оно вызывает нужный из ваших Timer1_Int, PWM0_Int и т.д. Кто из них в данный момент нужен - он узнает из регистра [pc,#-0xFF0]. Подробности об этом регистре - в документации. Это регистр VICVectAddr.

Не знаю, как насчёт его прибиваемости гвоздями, но у меня в программе роль гвоздей играл не
Код
            ldr     pc, [pc,#-0xFF0]    ; 18 Jump directly to the address given by the AIC


а
Код
#pragma vector=0x18
__irq __arm void irq_handler(void)

Если я создам, к примеру, в main.cpp для FIQ:
Код
#pragma vector=0x1С
__fiq __arm void fiq_handler(void)

То адрес этого хэндлера так же будет совпадать с тем, что расположен по 0x3C!
Я говорю о том, что не используя cstartup.s79 в IARe, а обработчик irq_handler, описанный мной в основной программе и загрузчике идентичны. Проверено через листинги и бинарники.

Вопрос для меня остался только за тем, как корректно предопределить адрес основной программы и что лежит по адресам 0x6000-0x603B?
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 24 2008, 21:15
Сообщение #43


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Кстати, порывшись в опциях XLINK, обнаружил возможность копирования той или иной области в указанную, т.о. мне для основной программы можно в *.xcl файле прописать такое:

Код
-DROMSTART=06040    //начало ОП
-DROMEND=0FFFF    //конец ОП

-Z(CODE)INTVEC=00-3f //вектора ОП
-KINTVEC=06000,1    //копия векторов


Загрузчик при получении файла-прошивки ОП (скорее всего в ней будет удалён начальный кусок, занятый под загрузчик, чтобы не передавать лишнего) может увидеть реальное расположение точки входа в ОП по адресу 0x6020 (после удаления начального куска станет 0x0020). Зачем такой изврат? Просто меня смущает неясность расположения этой точки входа и не может ли она измениться при смене версии IARа? А так - всё предопределено.

Сообщение отредактировал Altemir - May 24 2008, 21:22
Go to the top of the page
 
+Quote Post
Altemir
сообщение May 26 2008, 19:06
Сообщение #44


Местный
***

Группа: Свой
Сообщений: 249
Регистрация: 2-05-06
Из: Россия, Поволжье
Пользователь №: 16 686



Всё сделал. Всё работает. Никакой правки и копания в cstartup.s79 не потребовалось, прекрасно обошёлся #pragma и настройкой *.xcl. Убить загрузчик не получилось smile.gif Всем спасибо за наводки.
Go to the top of the page
 
+Quote Post
zltigo
сообщение May 26 2008, 19:31
Сообщение #45


Гуру
******

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



Цитата(Altemir @ May 26 2008, 21:06) *
Всё сделал.

Сделали жалкую пародию на систему с тупейшим, жестким и совершенно не нужным разделением на IRQ и FIQ и соответственно ничего из написанного на поняли. Печально.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post

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

 


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


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