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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Самозагрузчик
kolobok0
сообщение Apr 8 2016, 14:07
Сообщение #16


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Непомнящий Евгений @ Apr 8 2016, 08:37) *
...* как тестировали? ..Каждый модуль - как отдельный проект?...у вас код запускался из flash?
...Или не применяли команды, которые работают с фиксированными адресами, только по смещению?
* где жила системная библиотека (общая для всех модулей)?
...Или все хранится в куче?
... как позвать функцию из другого модуля?


- стандартный отладчик только на уровне азма конечно же, кроме загрузчика. юзается в основном дебажный вывод и мощная система логгирования при
фатальных ошибках.
- каждый модуль отдельный проект, работает из флэша.
- вся адресация относительная.
- все библиотеки = модули(фрииртос, фаты, стандартная либа, менеджэр памяти - их вообщето два, но для модулей - так-же в модуле отдельном)
- куча используется
- загрузчик делает позднее связывание модулей. т.е. есть понятия импортируемых и экспортируемых функций, необходимых аппаратных прерываний,
версии модуля и запрос версии.
- функции зовутся как обычно (в тексте это имеет маленький префикс - вот и всё отличие)

зачем = повышенная отказоустойчивость. и минимум требований к фазе дистанционной апгрэйта кода.

(круглый)



Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 12 2016, 12:44
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Сделал, но чего то не получается запустить основную программу
в чем может быть проблема?

утилитой ST Link проверяю - файл записался и лежит правильно в памяти
Загрузчик у меня такой:
CODE

#define FILE_NAME "loader.bin"
#define APP_ADDRESS (uint32_t)0x08008000


do {
/* Монтируем. Если нет файла - выходим на загрузку */
if ((rc = f_mount(0, &fatfs)) == 0) {
PRINTF("INFO: mount OK\r\n");
} else {
PRINTF("ERROR: mount fs\n");
break;
}

/* Открыть на чтение */
rc = f_open(&fil, FILE_NAME, FA_READ);
if (rc == 0) {
PRINTF("INFO: Loader file %s open OK\n", FILE_NAME);
} else {
PRINTF("INFO: Loader file %s doesn't exist. Continue booting", FILE_NAME);
break;
}

/* стираем секторы 2...4*/
FLASH_Unlock();
delay_ms(50);

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_2, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_3, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}

if(FLASH_COMPLETE == FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3)) {
PRINTF("Erase sector OK\n");
led_toggle(LED3);
}


/* Читаем файл и записываем в секторы flash */
bytes = 0;
addr = APP_ADDRESS;
do {
bw = 0;
rc = f_read(&fil, buf, sizeof(buf), &bw);
if (rc == 0 && bw > 0) {
bytes += bw;
for(i = 0; i < bw; i++) {
FLASH_ProgramByte(addr, buf[i]);
addr++;
}
PRINTF("%d bytes written\n", bytes);
led_toggle(LED4);
delay_ms(50);
}
} while (bw);

rc = f_close(&fil);

// Стираем файл
/* Если файл существует - удалим его */
// rc = f_unlink(FILE_NAME);

} while (0);

/* Disable all interrupts */
RCC->CIR = 0x00000000;

/* Делаем старт по адресу */
JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4);
Jump_To_App = (pFunction) JumpAddr;

/* Initialize application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APP_ADDRESS);
Jump_To_App();


Я вижу отладчиком, что до джампа он доходит - а дальше аут

основная прога использует такой скрипт линкера, где установлены адреса:

define symbol __ICFEDIT_intvec_start__ = 0x08008000;
define symbol __ICFEDIT_region_ROM_start__ = 0x08008000;

+ сделал коментарий в вызове из ассемблера SystenInit() - так это уже сделано в загрузчике
компилю образ проги и получаю бинарник program.bin

CODE
;Reset_Handler

; LDR R0, =SystemInit
; BLX R0
LDR R0, =__iar_program_start
BX R0


В чем может быть еще засада?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 12:52
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(inventor @ Apr 12 2016, 15:44) *
Я вижу отладчиком, что до джампа он доходит - а дальше аут

А поподробнее? В окне дизассемблера нашли инструкцию, которая делает не то, что нужно? Посмотрели значения соответствующих регистров?
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Apr 12 2016, 13:11
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(kolobok0 @ Apr 8 2016, 17:07) *
- загрузчик делает позднее связывание модулей. т.е. есть понятия импортируемых и экспортируемых функций, необходимых аппаратных прерываний,
версии модуля и запрос версии.

А вот это самодельное или от линукс-арм прикрутили?
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 12 2016, 13:12
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Цитата(scifi @ Apr 12 2016, 15:52) *
А поподробнее? В окне дизассемблера нашли инструкцию, которая делает не то, что нужно? Посмотрели значения соответствующих регистров?

делает branch BLX R8
тока в R8 почему то 0x08009f85
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 13:37
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(inventor @ Apr 12 2016, 16:12) *
тока в R8 почему то 0x08009f85

А это хорошо или плохо? Мы же не знаем точку входа в вашу основную программу. Может быть, она там и есть.
Советую отладчиком пройти по этой инструкции и посмотреть, куда она выводит. И кейл, и яр позволяют загрузить отладочную информацию для двух программ (загрузчика и основной программы), то есть переход будет прозрачным для отладчика. Весьма вероятно, что падает основная программа, потому что вы что-то не учли.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Apr 12 2016, 14:26
Сообщение #22


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Kabdim @ Apr 12 2016, 16:11) *
А вот это..


самодельное.
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 12 2016, 14:26
Сообщение #23


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(inventor @ Apr 12 2016, 15:44) *
Код
    /* Disable all interrupts */
       RCC->CIR = 0x00000000;
    
      /* Делаем старт по адресу */
    JumpAddr = *(__IO uint32_t*) (APP_ADDRESS + 4);
    Jump_To_App = (pFunction) JumpAddr;

    /* Initialize application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) APP_ADDRESS);
    Jump_To_App();


Так делать некорректно!
Во первых не устанавливается новый адрес таблицы векторов ( VTOR )
Во вторых указатель стека будет модифицирован и не будет соответствовать тому что лежит по APP_ADDRESS

И если хотите отлаживать приложение без бутлоадера (если это разные проекты) то надо у IAR в макросах установить запись VTOR - тогда можно без проблем отлаживать.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 12 2016, 14:49
Сообщение #24


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(KRS @ Apr 12 2016, 17:26) *
Во первых не устанавливается новый адрес таблицы векторов ( VTOR )

По-моему, это все же дело приложения, а не загрузчика.

Цитата(KRS @ Apr 12 2016, 17:26) *
Во вторых указатель стека будет модифицирован и не будет соответствовать тому что лежит по APP_ADDRESS

Где?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 12 2016, 15:03
Сообщение #25


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(aaarrr @ Apr 12 2016, 17:49) *
Где?

Строго говоря, компилятору разрешается крутить указатель стека в любой момент, причём в любую сторону. Так что я бы сказал, что такой способ установки указателя стека предполагает некое везение. Ассемблерный код здесь идеологически более правильный. Как обычно, агитирую за свой вариант biggrin.gif
Код
static const uint16_t jump2fw[] =
{
    0xF850, 0xDB04, /* LDR.W SP, [R0], #4   */
    0x6800,         /* LDR.W R0, [R0]       */
    0x4700,         /* BX R0                */
};
((void (*)(int))(1 + (int)jump2fw))(0x08010000);
Go to the top of the page
 
+Quote Post
KRS
сообщение Apr 12 2016, 15:41
Сообщение #26


Профессионал
*****

Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555



Цитата(aaarrr @ Apr 12 2016, 17:49) *
По-моему, это все же дело приложения, а не загрузчика.

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




Цитата(scifi @ Apr 12 2016, 18:03) *
Как обычно, агитирую за свой вариант biggrin.gif


Ну можно и встроенным асмом обойтись...
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Apr 12 2016, 16:49
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(KRS @ Apr 12 2016, 18:41) *
Нет - загрузчика! Потому что старт приложения происходит по RESET вектору который лежит в таблице прерываний, соотв. VTOR обязан указывать туда...

Как минимум спорно. Приложение может и не придерживаться этих правил, т.к. не предназначено для непосредственного исполнения после аппаратного сброса.

Цитата(scifi @ Apr 12 2016, 18:03) *
Как обычно, агитирую за свой вариант biggrin.gif

А я - за свой sm.gif
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();
Go to the top of the page
 
+Quote Post
inventor
сообщение Apr 13 2016, 06:49
Сообщение #28


Знающий
****

Группа: Свой
Сообщений: 524
Регистрация: 25-12-08
Из: Москва
Пользователь №: 42 748



Сделал самозагрузчик,
забыл вызвать функцию NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000); в основной программе
теперь у меня такой вопрос
вот мой загрузчик грузит только то, что есть на внутренней flash
как быть с теми функциями и данными, которые должны располагаться
на RAM памяти? кто должен их располагать правильно?
надо ли так же перераспределить и память RAM, между загрузчиком и основной программой?
Go to the top of the page
 
+Quote Post
scifi
сообщение Apr 13 2016, 06:59
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(aaarrr @ Apr 12 2016, 19:49) *
А я - за свой sm.gif
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();

Скобок много - в глазах рябит biggrin.gif
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Apr 13 2016, 07:54
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(inventor @ Apr 13 2016, 07:49) *
вот мой загрузчик грузит только то, что есть на внутренней flash
как быть с теми функциями и данными, которые должны располагаться
на RAM памяти? кто должен их располагать правильно?
надо ли так же перераспределить и память RAM, между загрузчиком и основной программой?

Ничего специально делать не нужно. Если у Вас основная программа не bare bones (иными словами, написана в рамках среды разработки и с использованием стандартных библиотек среды), то перед переходом в main() втихую вызывается инициализация RAM. Она прочищает/устанавливает необходимые области/переменный RAM. Все, что пользовал загрузчик, будет бесследно "перезатерто".

Цитата(aaarrr @ Apr 12 2016, 17:49) *
Код
    __set_MSP(*((uint32_t *)IMAGE_START));
    (*((void (**)(void))(IMAGE_START + 4)))();

Вставлю свои 5 копеек: в ассемблерном стартовом файле я дописал:

Код
VTOR            EQU     (0xE000E000 + 0x0D08)                
StartMainApp    PROC   ; R0 - parameter with the APP vector table address
                EXPORT  StartMainApp               [WEAK]
                LDR     R1, =VTOR                  ; Load VTOR register address
                STR     R0, [R1]                   ; Store to VTOR to relocate the vector table
                LDR     SP, [R0]                   ; Reinit the user stack
                LDR     R0, [R0, #4]               ; Get the user entry point...
                BX      R0                         ; ... and jump to it
                ENDP

В С-шном файле вызов выглядит как:
Код
extern StartMainApp(uint32_t vector);
...
StartMainApp(0x08000000 + 0x4000); // для моего случая программы с 16К

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 Текстовая версия Сейчас: 18th July 2025 - 17:47
Рейтинг@Mail.ru


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