Перейти к содержанию
    

LPC4337, свой загрузчик. Не получается запустить приложение.

А зачем вообще ассемблер? Вот так я запускаю приложение. Не утверждаю, что это самый правильный вариант, но рабочий.

// Вот эту функцию вызываю для запуска приложения
__noreturn void Boot::runApp() {
    remapVectorTableBundle(APP_ADDRESS);
    jump2app();
    while (1);
}

// Непосредственно сам запуск
__noreturn void Boot::jump2app() {
    const uint32_t appResetAddr = *reinterpret_cast<const uint32_t *>(APP_ADDRESS + 4);
    typedef  void ( *pFunction )( void );
    auto pAppEntry = (pFunction)( appResetAddr );
    pAppEntry();
    while (1);
}

// В другом файле
void remapVectorTableBundle( const uint32_t address ) {
    __set_MSP(*reinterpret_cast<const uint32_t *>(address));
    nvic_vector_table_set(NVIC_VECTTAB_FLASH, address); // VTOR здесь модифицируется
}

 

Т.е. для запуска приложения я подготавливаю стек MSP, устанавливаю VTOR (здесь есть спорные моменты, что это можно делать и в приложении, а в Crotex-M0 этого регистра вообще нет) и выполняю код по адресу "начало таблицы векторов + 4 байта"....

Всё...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

5 часов назад, haker_fox сказал:

А зачем вообще ассемблер?

Ассемблер ничем не плох. Плохо только то, что ТС пытается им пользоваться даже не разобравшись в его работе.

5 часов назад, haker_fox сказал:

Вот так я запускаю приложение. Не утверждаю, что это самый правильный вариант, но рабочий.

И да - имхо не совсем правильный. А то что рабочий - просто повезло. :wink2:

Ведь APP_RESET поди - константа? В таких вещах volatile (для указателя) будет совсем не лишним. Некоторые компиляторы, видя, что идёт обращение к далёкому адресу флешь для чтения единственного слова const-данных, вполне себе могут сделать копию содержимого того дальнего слова возле точки чтения. Чтобы уменьшить число команд. И будет у Вас не чтение из реальной таблицы векторов, а загрузка некоего значения, которое должно находиться по адресу APP_RESET+4 (по мнению компилятора на момент компиляции). Или загрузка из совсем другого адреса флешь (командой LDR); или загрузка непосредственного значения (командой MOV) прямо из кода команды. Если компилятор решит, что он заведомо знает что там будет находиться - получите баг. Такое может случиться когда компилятор "поумнеет" (выйдет новая версия).

Именно поэтому регистры периферии все необходимо объявлять с volatile. Даже те, которые read-only и к которым происходит только единственное обращение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

46 minutes ago, jcxz said:

Именно поэтому регистры периферии все необходимо объявлять с volatile.

Про оптимизацию чтения - очень занятно! Спасибо! Я исправлю в своём коде. Но при чём здесь регистры всё же, непонятно) Или это уже просто замечание к сказанному?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

57 минут назад, haker_fox сказал:

Но при чём здесь регистры всё же

Так - по той же причине. Чтобы компилятор не мог оптимизировать чтение read-only регистров. Потому как они по сути без volatile будут выглядеть как участок read-only памяти.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...