haker_fox 61 19 апреля, 2023 Опубликовано 19 апреля, 2023 · Жалоба А зачем вообще ассемблер? Вот так я запускаю приложение. Не утверждаю, что это самый правильный вариант, но рабочий. // Вот эту функцию вызываю для запуска приложения __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 байта".... Всё... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 19 апреля, 2023 Опубликовано 19 апреля, 2023 · Жалоба 5 часов назад, haker_fox сказал: А зачем вообще ассемблер? Ассемблер ничем не плох. Плохо только то, что ТС пытается им пользоваться даже не разобравшись в его работе. 5 часов назад, haker_fox сказал: Вот так я запускаю приложение. Не утверждаю, что это самый правильный вариант, но рабочий. И да - имхо не совсем правильный. А то что рабочий - просто повезло. Ведь APP_RESET поди - константа? В таких вещах volatile (для указателя) будет совсем не лишним. Некоторые компиляторы, видя, что идёт обращение к далёкому адресу флешь для чтения единственного слова const-данных, вполне себе могут сделать копию содержимого того дальнего слова возле точки чтения. Чтобы уменьшить число команд. И будет у Вас не чтение из реальной таблицы векторов, а загрузка некоего значения, которое должно находиться по адресу APP_RESET+4 (по мнению компилятора на момент компиляции). Или загрузка из совсем другого адреса флешь (командой LDR); или загрузка непосредственного значения (командой MOV) прямо из кода команды. Если компилятор решит, что он заведомо знает что там будет находиться - получите баг. Такое может случиться когда компилятор "поумнеет" (выйдет новая версия). Именно поэтому регистры периферии все необходимо объявлять с volatile. Даже те, которые read-only и к которым происходит только единственное обращение. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 19 апреля, 2023 Опубликовано 19 апреля, 2023 · Жалоба 46 minutes ago, jcxz said: Именно поэтому регистры периферии все необходимо объявлять с volatile. Про оптимизацию чтения - очень занятно! Спасибо! Я исправлю в своём коде. Но при чём здесь регистры всё же, непонятно) Или это уже просто замечание к сказанному? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 19 апреля, 2023 Опубликовано 19 апреля, 2023 · Жалоба 57 минут назад, haker_fox сказал: Но при чём здесь регистры всё же Так - по той же причине. Чтобы компилятор не мог оптимизировать чтение read-only регистров. Потому как они по сути без volatile будут выглядеть как участок read-only памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться