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

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> Стартовый загрузчик, с нуля
menzoda
сообщение Oct 8 2014, 19:17
Сообщение #31


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Не надо ничего сдвигать на 7 битов! Прочитай внимательнее про этот регистр: эти биты не используются, потому что таблица прерываний должна быть выровнена по определенному адресу, кратному размеру таблицы, округленному до следующей степени двойки.

Второе. Никаких жестко заданных 0x8105! При следующей компиляции этот адрес может быть совсем другим. Я же сказал, как его достать: читаешь значение из второго вектора в таблице основного ПО, которая всегда находится в известном (определенном тобой) месте.

Надо бы проект посмотреть, да у меня IAR не стоит. Попробуй для начала просто отладить переход: вставь эту инструкцию в стартап файл загрузчика, сразу в ResetHandler, пускай переходит куда-нибудь рядом, через пару адресов. Попробуй другие инструкции вроде BX, которые переходят по адресу из указанного регистра. Только почитай про них внимательнее, при использовании BX и BLX младший бит адреса назначения должен быть установлен.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 8 2014, 19:42
Сообщение #32


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Oct 8 2014, 23:17) *
Не надо ничего сдвигать на 7 битов! Прочитай внимательнее про этот регистр: эти биты не используются, потому что таблица прерываний должна быть выровнена по определенному адресу, кратному размеру таблицы, округленному до следующей степени двойки.

В хидере 35 прерываний и добавим 16 исключений, как написано в руководстве на ядро, получили 51, ближайшая степень двойки - 64, умножаем на 4 и получим 0x100. Этому числу должен быть кратен адрес таблицы векторов, т.е. 0x7000 подходит.
Далее читаю описание полей регистра VTOR:
Бит 29 TBLBASE - расположение таблицы в оперативке(1) или во флеш(0)
Биты 28:7 TBLOFF - Смещение таблицы относительно начала области кода или области ОЗУ,т.е. к 0x7000 добавляем справа 7 нулевых битов и получаем 0x380000 и записываем это число в регистр VTOR.

Цитата(menzoda @ Oct 8 2014, 23:17) *
Второе. Никаких жестко заданных 0x8105! При следующей компиляции этот адрес может быть совсем другим. Я же сказал, как его достать: читаешь значение из второго вектора в таблице основного ПО, которая всегда находится в известном (определенном тобой) месте.

Пока не трогаю записанные данные по адресу 0x7000, т.е. никуда ничего не перемещаю, а пытаюсь маленькой программой запустить большую, расположеннуюв другом месте памяти. И адрес 8105 не меняется в моём случае.

Сообщение отредактировал ДЕЙЛ - Oct 8 2014, 19:43
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 8 2014, 20:55
Сообщение #33


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Почему-то в пашаговом режиме после перехода по адресу программа в другом конце памяти запускается иногда после команды перехода, а после нажатия кнопки сброса никаких движений.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 9 2014, 04:54
Сообщение #34


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Не так считаешь. Векторов прерываний 51, в байтах это 51*4 = 204. Округляем до 256, в двоичном виде это будет 100000000, младшие 7 бит уже равны нулю как ни крути. Выбираем адрес кратный 256, ты выбрал 0x7000, и пишем его прямо туда, не сдвигая, потому что у всех адресов кратных 256 младшие 8 бит будут всегда равны нулю.

В документации всё написано, хоть и несколько запутано:
Цитата
Vector table base offset field. It contains bits[29:7] of the offset of the table base from the bottom of the memory map.

Поле смещения таблицы векторов. Оно содержит биты [29:7] смещения таблицы относительно начального адреса. То есть надо взять смещение 0x7000, взять из него биты 29:7, получившееся число 0xE0 записать в биты 29:7 регистра. Это то же самое, что и запись в регистр числа 0x7000.

Цитата
Почему-то в пошаговом режиме после перехода по адресу программа в другом конце памяти запускается иногда после команды перехода, а после нажатия кнопки сброса никаких движений.

Не понял.

Кстати, что-то я не вижу в документации примеров использования инструкции B как у тебя, там только говориться про то, что можно указать метку или значение относительно текущего адреса в виде [PC, #imm]. Попробуй использовать:
Код
MOV R0, #0x8105
BX R0


Кроме того B может скакать только на +-2Кб, а у тебя тут вроде больше. Странно, почему ассемблер не ругнулся. Пройдись внимательно по шагам по ассемблерному коду (а не по сишному), точно вылетает на инструкции перехода? Покажи дизассемблер участка с этим переходом (что за инструкция там действительно находится).


Нашел у себя на работе IAR, в симуляторе всё работает, странно. Но всё равно ты попробуй перейти с помощью другой инструкции.

Сообщение отредактировал menzoda - Oct 9 2014, 06:33
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 9 2014, 06:47
Сообщение #35


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



насчёт перескока на 2кб на какой странице мануала написано? Надо попробовать, а симулирование и реальность не всегда совпадают, как я заметил.


Цитата(menzoda @ Oct 9 2014, 08:54) *
Поле смещения таблицы векторов. Оно содержит биты [29:7] смещения таблицы относительно начального адреса. То есть надо взять смещение 0x7000, взять из него биты 29:7, получившееся число 0xE0 записать в биты 29:7 регистра. Это то же самое, что и запись в регистр числа 0x7000.

пробовал разные варианты - записывал 0x380000 и 0x7000, в отладчике наблюдалось число 0xE0.
Цитата
Не понял.

Имею ввиду, что программа из флеши запускается в следующем шаге после строки B 0x8105 при нажатии кнопки F10 в пошаговом режиме отладки, т.е. переходит в то место и запускает программу, а когда отключаю JTAG и нажимаю на сброс, то никаких переходов нет, контроллер не шевелится.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 9 2014, 07:30
Сообщение #36


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата
насчёт перескока на 2кб на какой странице мануала написано?

Тут я ошибся, наверное посмотрел на набор инструкций Thumb. У Cortex-M3 Thumb2 и там можно прыгать на 16 Мб, вот дока.

Цитата
пробовал разные варианты - записывал 0x380000 и 0x7000, в отладчике наблюдалось число 0xE0.

0xE0 это правильное значение: если взять биты 29:7 от 0x7000, то как раз выйдет 0xE0. Почему у тебя при записи 0x380000 получается 0xE0 я не знаю, может перепутал чего? Во всяком случае, 0xE0 это хорошо.

Цитата
Имею ввиду, что программа из флеши запускается в следующем шаге после строки B 0x8105 при нажатии кнопки F10 в пошаговом режиме отладки, т.е. переходит в то место и запускает программу, а когда отключаю JTAG и нажимаю на сброс, то никаких переходов нет, контроллер не шевелится.

То есть в отладчике переход всё-таки работает? Попробуй пошагать дальше, может ошибка вываливается где-нибудь в другом месте, в отладчике ты до него просто не доходишь.

Остановись на инструкции перехода, шагни вперед. Перешло к основному ПО по адресу 0x8105? Если всё отлично - шагай дальше, там будет SystemInit, потом __iar_program_start, из него будет вызвана main основного ПО. Вот хотя бы до main дойди. Заметь, при хождении по основному ПО никакие метки не будут подсвечены (не будет написано, что это __iar_program_start или main), будет сплошная простыня с инструкциями, так что тебе придется посмотреть адреса всех этих меток в map-файле основного ПО и сверять всё вручную.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 9 2014, 08:53
Сообщение #37


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Цитата(menzoda @ Oct 9 2014, 11:30) *
То есть в отладчике переход всё-таки работает? Попробуй пошагать дальше, может ошибка вываливается где-нибудь в другом месте, в отладчике ты до него просто не доходишь.

Под отладчиком после ассемблерной инструкции перехода программа работает в реальном режиме времени, но её можно остановить и увидеть, что всё крутится в адресах после 7000. Мошть ещё нужно указатель стека на нужное место поставить, как мне посоветовали на другом форуме?

Сообщение отредактировал ДЕЙЛ - Oct 9 2014, 08:54
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 9 2014, 10:15
Сообщение #38


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата
Мошть ещё нужно указатель стека на нужное место поставить, как мне посоветовали на другом форуме?

Это идея. Ведь адрес вершины стека извлекается из первого вектора после сброса, а мы при переходе к основному ПО ничего не сбрасываем. Формально говоря, надо бы перед переходом самому извлечь это значение и записать в регистр SP, или можно это сделать в основном ПО в стартап-файле. Однако, не факт, что это является причиной ошибки.

Сейчас адрес стека достается основному ПО по наследству от загрузчика. Какие могут быть потенциальные проблемы? Во-первых, загрузчик может использовать значительную часть стека и основному ПО достанется урезанный участок памяти, которого может не хватить, но так как твой загрузчик вообще не использует стек этим вариантом можно пренебречь. Во-вторых, проекты загрузчика и основного ПО могут иметь разное расположение стека: стек загрузчика может пересекаться с областью данных основного ПО. Таким образом основное ПО, работая с данными в RAM, может попортить себе этот неправильно заданный стек.

Последняя ситуация более вероятна, но если это и она странно, что в отладчике всё работает. Тем не менее попробуй задать правильное значение стека перед переходом и посмотри что будет. Если не поможет то остается трассировать. Расставляешь на разных этапах загрузчика и основного ПО дерганье выводами МК, так же не забываешь про исключения (HardFault и иже с ним). Запускаешь и смотришь: ага, эта дернулась, значит загрузчик запустился, а эта не дернулась, значит в основное ПО не перешел, выходит проблема где-то между этими этапами. Постепенно передвигая дерганье ногами ближе к друг-другу определяешь место поломки, ну а дальше будет видно.
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Oct 9 2014, 19:26
Сообщение #39


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Железно заработало yeah.gif
дело было ещё и в указателе стека. В этом прикреплённом проекте в тестовой программе для вызова главной нужно написать такой код:
Код
unsigned int *VTOR;
int main()
{
VTOR = (unsigned int*)0xE000ED08; //адрес данного регистра из хидера
*VTOR = 0x7000; //смещение таблицы векторов - из настроек линкера
asm ("mov r13, #0x2448"); //запись в регистр стека младших байтов значения указателя стека основной программы, взятого из ячейки с адресом 0x7000;
asm ("movt r13, #0x1000"); //запись в регистр стека старших байтов значения указателя стека основной программы, взятого из ячейки с адресом 0x7000;
asm ("B 0x8105"); //Безусловный переход по адресу обработчика прерывания сброса, прочитанного из ячейки 0x7002;
}

Можно было бы поумнее и правильнее код сделать, но для понимания принципа этого хватит.

теперь попробую назад в загрузчик из главной программы зайти

Цитата(toweroff @ Oct 8 2014, 18:52) *
bb-offtopic.gif
ДЕЙЛ, я, конечно, ничего против не имею, но такая боевая расцветка темы оформления каждый день по несколько часов сидения у монитора глаза не заворачивает на затылок? sm.gif

bb-offtopic.gif Зато оперативка экономится, отключил всё ненужное. Ноуту лет 15, в нём есть привод дискет, два разъёма усб, всамделишный LPT и COM-порты wink.gif Но зато экран большой и нет отвлекающего выхода в тырнет.
Go to the top of the page
 
+Quote Post
menzoda
сообщение Oct 10 2014, 04:59
Сообщение #40


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 13-09-12
Пользователь №: 73 530



Цитата
Железно заработало

Наконец! Всем миром загрузчик помогали делать! Зато какой опыт!

Цитата
теперь попробую назад в загрузчик из главной программы зайти

Уж это должно быть несложно - просто вызвать программный сброс. Главный вопрос сбросит ли он VTOR, вроде сбрасывает, но лучше уточнить, периферию то он точно сбрасывает.

Цитата
Зато оперативка экономится, отключил всё ненужное.

Цвет то на оперативку не влияет никак, а так я сам с классической темой сижу, только цвета стандартные - серо-мышиные, а не вырвиглазный зеленый. biggrin.gif
Go to the top of the page
 
+Quote Post
ДЕЙЛ
сообщение Feb 16 2015, 12:28
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 234
Регистрация: 7-11-13
Пользователь №: 79 085



Оставлю тут свой код загрузчика на всякий случай, а то на домашнем компе ненадёжно. Программа принимает файл от прикреплённой программы, написанной на DELPHI. Успеть отправить надо в течение минуты после сброса.

Код
#include "iolpc1778.h"
#include "LPC17xx.h"

#define IAP_LOCATION 0x1fff1ff1 //точка входа в IAP (страница 896 мануала)  
unsigned int command[5];
unsigned int result[2];
typedef void (*IAP)(unsigned int[], unsigned int[]);  


unsigned char DATA[30000];
unsigned int command[5];
unsigned int result[2];
unsigned char RX;
unsigned int index_RX;
unsigned char RX_PAKET[18];
unsigned char CHSUM, FlagRX;
unsigned int indexM, pauza, i;
unsigned int adr_copy, stek;
unsigned int *adres_stek;
unsigned char OutPortByte;
int sektor;

void Out_UART0(); //otpravka paketa po UART0


void main(void)
{  
   { //INIT

   { //init UART0  
IOCON_P1_25 = 0; //PIO
FIO1DIR     = 0x2200000; //Выходы PIN1_25, PIN1_11
PCONP      |= 0x8;
IOCON_P0_02 = 0x1;
IOCON_P0_03 = 0x1;
   }


FIO0DIR     = 0x4+0x8;


SCS        |= 0x20; //подключение осциллятора
while(!(SCS&0x40)){} //ожидание запуска

PLL0CON |= 0x01;
PLL0CFG |= 0x09;
PLL0FEED = 0xAA;  
PLL0FEED = 0x55;    
CCLKSEL |= 0x100;


PCLKSEL    = 1;
CLKSRCSEL |= 1;
U0LCR     |= 0x83;   //razrecchenie dostupa k delitely
U0DLL      = 0xC8;   //0xF0;//0xA0; //0x14;  //0x4E;  //nastrojka delitelya
U0LCR     &=~0x80;   //zapret dostupa k delitely
U0IER     |= 0x1+0x4;//Разрешение прерываний UART0

//__enable_irq();              //Разрешение
//__set_FAULTMASK(0);            //всех прерываний
//__set_BASEPRI(0);              //Отключение маскирования
//__set_CONTROL(0);

AIRCR = 0x05FA0200;
IP1   = 0x00000800;
}
  NVIC_EnableIRQ(UART0_IRQn);    //Enable IRQ UART0 (ISER0=32)
  indexM = 0;
  index_RX = 1;
  

while(1)
{
    
  
  if (index_RX>5)
  {
   if ((DATA[index_RX-1]==0x11)&(DATA[index_RX-2]==0x22)&(DATA[index_RX-3]==0x33)&(DATA[index_RX-4]==0x44)) самопальный признак конца файла HEX
  {  
    FlagRX = 0;
  

//COPY_FLASH
      
adr_copy = (unsigned int)&DATA[4096];
IAP iap_entry;
iap_entry = (IAP) IAP_LOCATION;


for (sektor=1; sektor<5; sektor++)
{
//_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______//
{

command[0] = 50; //код команды
command[1] = sektor;  //начальный номер сектора
command[2] = sektor;  //конечный номер сектора

iap_entry (command, result);
}
//_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______//




//_______СТЕРЕТЬ СЕКТОР_______//
{

command[0] = 52;     //код команды
command[1] = sektor;      //начальный номер сектора
command[2] = sektor;      //конечный номер сектора
command[3] = 120000; //системная тактовая частота в кГц

iap_entry (command, result);
}
//_______СТЁРЛИ СЕКТОР______//

//_______ПОДГОТОВИТЬ СЕКТОР К ЗАПИСИ_______//
{

command[0] = 50; //код команды
command[1] = sektor;  //начальный номер сектора
command[2] = sektor;  //конечный номер сектора

iap_entry (command, result);
}
//_______ПОДГОТОВИЛИ СЕКТОР К ЗАПИСИ______//




//_______КОПИРОВАТЬ ОПЕРАТИВНУЮ ПАМЯТЬ ВО ФЛЕШ_______//
{

command[0] = 51;         //код команды
command[1] = 0x1000*sektor;     //начальный адрес перезаписываемой флеш
command[2] = adr_copy+4096*(sektor-1); //начальный адрес оперативной памяти, откуда нужно копировать
command[3] = 4096;        //число байт для копирования
command[4] = 120000;     //системная тактовая частота в кГц
  
iap_entry (command, result);

}
//_______СКОПИРОВАЛИ СЕКТОР______//
      




//END_FLASH
}

VTOR = 0x1000;
adres_stek = (unsigned int*)0x1000;
stek = (unsigned int)*adres_stek;
__set_MSP(stek);

asm("mov R1, #0x1004");
asm("ldr R2, [R1]");
asm("BX R2");


    
  }
  }  
}

}





void Out_UART0()
{
while (!(U0LSR&0x20));
U0THR=0xA0;                  //признак ответа  для программы на ПК
}

void UART0_IRQHandler(void)

{
  DATA[index_RX] = U0RBR;
  index_RX++;
  NVIC_ClearPendingIRQ(UART0_IRQn);
  return;
}


Прикрепленные файлы
Прикрепленный файл  __________.rar ( 439.1 килобайт ) Кол-во скачиваний: 12
 
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 23:10
Рейтинг@Mail.ru


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