Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба Загрузка в стек должна производиться инструкцией MSR LDR R1, [R0] MSR MSP, R0 , а загрузка в PC - банальным переходом LDR R1, [R0, 4] BX R1 , но можно и LDR-ами грузить. Каково значение бита 0 (nPRIV) в регистре CONTROL у CPU? В непривилегированном режиме грузить LDR-ами в SP и PC запрещено. Судя по названиям файлов проекта, в нем крутится какая-то RTOS, а значит она, скорее всего, "сделала все правильно" и установила непривилегированный режим. Насколько я помню (лень открывать мануал), из режима потока его снять обратно не получится, только через обработчик прерывания. Сделайте это, например, через синхронный SVC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 50 минут назад, arm-user сказал: При попытке это выполнить происходит Hard Fault. Тут я уже ничего не понимаю. Вам обработчик HF рассказывает о том, что у вас произошло: Undefined instruction UsageFault: 0 = no undefined instruction UsageFault 1 = the processor has attempted to execute an undefined instruction. When this bit is set to 1, the PC value stacked for the exception return points to the undefined instruction. An undefined instruction is an instruction that the processor cannot decode. Т.е. - попытка выполнения неправильной команды CPU. Сделайте расшифровку причины HF. А потом, по адресу PC, посмотрите на эту команду. 25 минут назад, Arlleex сказал: Загрузка в стек должна производиться инструкцией MSR Почему обязательно MSR? Чем банальная MOV SP, Rx плоха? StartWorkFw: LDR R0, =PFLASH_BEGIN_C + FW_WORK_BEGIN LDMIA R0!, {R1, R2} MOV SP, R1 BX R2 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 2 минуты назад, jcxz сказал: Почему обязательно MSR? Чем банальная MOV SP, Rx плоха? Ничем. Не обязательно MSR. Это я поспешил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 32 минуты назад, Arlleex сказал: Судя по названиям файлов проекта, в нем крутится какая-то RTOS, а значит она, скорее всего, "сделала все правильно" и установила непривилегированный режим. Если это так, то передавать управление в другое приложение таким образом - чревато. Ибо оно не знает, что конфигурация процессора не соответствует послесбросовой (режим CPU, его управляющие регистры и активный SP). И поэтому уже оно может работать неверно. Если использовалась ОС, то перед передачей управления в другое приложение, нужно сперва привести CPU в исходное состояние. И периферию - тоже. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба Как я понял, у ТС RTOS уже во весь ход запущена к моменту вызова функции перехода на приложение. Так что да, чревато. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 1 hour ago, arm-user said: Может быть, что изменение стека запрещено по умолчанию Читайте про эту команду) Upd. Немного поспешил. Оказывается в теме уже были ответы) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 4 минуты назад, haker_fox сказал: Читайте про эту команду) Да не, выше jcxz дал, по идее, универсальный вариант, который не зависит от состояния CPU. Должно работать. Но, как уже было замечено, все инициализированное/измененное железо должно быть приведено в исходное состояние. Я бы банально сбросился через NVIC (разумеется, первыми командами проверив, что сброс вызван точкой перехода на приложение). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arm-user 0 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 6 hours ago, Arlleex said: Как я понял, у ТС RTOS уже во весь ход запущена к моменту вызова функции перехода на приложение. Так что да, чревато. Спасибо за отклики, попробую ответить. - scmRTOS была в этом коде. Для загрузчика отскреб ее насколько мог. Для выдачи в UART используются очереди сообщений от RTOS. Чтобы не тратить время на переделку их оставил и оставлены инклюды от scmRTOS. Но процессы и запуск самой RTOS отсутствуют. Все сейчас крутится в поллинге. А также есть прерывания от Ethernet и таймера. Но в момент перехода мы находимся в основном цикле и прерывания отключаются перед переходом. Есть ли тут какие-то еще подводные камни, которые я не знаю? - В ассемблерных процедурах перехода ничего не понимаю. Взял код, найденный на этом форуме в соседней ветке. Код на С также не заработал. Попробую предложенный выше. - Переход на приложение и планировлся через NVIC_Reset, но я не знаю, получится ли его отлаживать в таком режиме. Подхватит ли отладчик точки останова после ресета. Я почему-то решил, что нет, и убрал пока Ресет для теста. - Стек удалось изменить встроенной функцией __set_MSP(user_stack); Переход, похоже, тоже работает и сейчас проблема в том, что код приложения лежит где задумано, но сам "не знает" что он начинается с 0x1a008000. Буду с этим разбираться. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arm-user 0 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба Поправил код приложения, адреса встали на место, но проблема осталась. Попробовал код перехода, предложеннный выше (на скриншоте 1). Все равно на переходе уходит на ошибку. Чтобы понять на каком шаге происходит ошибка, разбил asm вставку на 2 - по одной строке в каждой. И в таком виде оно заработало. Есть ли объяснение почему? И второй вопрос - адрес перехода (R1) вычитывается 0x1A00C095 (в бинарнике, соответственно, также). Но дизассемблер говорит, что адрес Reset_Handler на единицу меньше 0x1A00C094. Почему так происходит и не надо ли подправить что-нибудь в процедуре перехода на эту тему? Подскажите, пожалуйста. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 20 минут назад, arm-user сказал: Чтобы понять на каком шаге происходит ошибка, разбил asm вставку на 2 - по одной строке в каждой. И в таком виде оно заработало. Есть ли объяснение почему? Потому что в "асм-вставке" написан полный бред. С чего вдруг чтение от R0 делаете? У вас же адрес объявлен как "r"(address). Естественно, что читать нужно не с R0, а с соответствующего аргумента. И вообще к регистрам напрямую лучше не обращаться. u32 i; asm( " LDR %0, [%1, #4] \n" " BX %0" : "=&r"(i) : "r"(address) : "memory"); i = i; как-то так. Кроме того - ещё про SP забыли. PS: И в отладчике смотреть нужно не на исходный код, а в окно дизассемблера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба arm-user, Вы лучше в асм-листинг функций перехода смотрите, а то этот inline asm - та еще могучая кучка со своим мусор..ом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 188 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 41 минуту назад, jcxz сказал: u32 i; asm(...); i = i; Интереса ради: зачем нужен i = i в конце? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
arm-user 0 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 1 hour ago, jcxz said: Потому что в "асм-вставке" написан полный бред. С чего вдруг чтение от R0 делаете? У вас же адрес объявлен как "r"(address). Естественно, что читать нужно не с R0, а с соответствующего аргумента. И вообще к регистрам напрямую лучше не обращаться. u32 i; asm( " LDR %0, [%1, #4] \n" " BX %0" : "=&r"(i) : "r"(address) : "memory"); i = i; как-то так. Кроме того - ещё про SP забыли. PS: И в отладчике смотреть нужно не на исходный код, а в окно дизассемблера. Окно дизассемблера не показывало текущую информацию. Разобрался, нашел галку прилинковать текущий debug контекст. SP не забыл, говорил, что для него заработала штатная функция __set_MSP(user_stack); С новым вариантом ассемблерной вставки стало существенно хуже, адрес перехода лежит в регистре R0, а операции производятся с другими регистрами 38 minutes ago, Arlleex said: Интереса ради: зачем нужен i = i в конце? наверное, это компилятору, чтобы не решил "оптимизировать" пустую функцию? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 242 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба 1 час назад, Arlleex сказал: Интереса ради: зачем нужен i = i в конце? Иначе IAR ругается на "неиспользуемую переменную". 53 минуты назад, arm-user сказал: С новым вариантом ассемблерной вставки стало существенно хуже, адрес перехода лежит в регистре R0, а операции производятся с другими регистрами А если ещё раз подумать? И почитать какой-нить учебник по системе команд используемого CPU. И затем - ещё раз внимательно посмотреть на результат компиляции? Всё там ok. PS: Чтобы было в R0 (более-менее вероятно), достаточно включить оптимизацию. 53 минуты назад, arm-user сказал: наверное, это компилятору, чтобы не решил "оптимизировать" пустую функцию? Ответ неверный. Как же он её оптимизирует, если у вас оптимизация выключена? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 18 апреля, 2023 Опубликовано 18 апреля, 2023 · Жалоба И второй вопрос - адрес перехода (R1) вычитывается 0x1A00C095 (в бинарнике, соответственно, также). Но дизассемблер говорит, что адрес Reset_Handler на единицу меньше 0x1A00C094. Почему так происходит и не надо ли подправить что-нибудь в процедуре перехода на эту тему? Ядро использует набор команд Thumb-2 (впрочем, других и не умеет), а признак его (набора) - "1" в младшем разряде того, что находится или будет находиться в счётчике команд (PC). Править ничего не надо: адрес в памяти 0x1A00C094, в должно PC загрузиться 0x1A00C094|0x00000001. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться