Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: CortexM3, запись данных в Program Counter.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Danis
Привет, коллеги по цеху!

Работаю в IAR, пишу на Си. Имеется надобность прочитать данные из ячейки flash по адресу 0x08000804 и записать их в регистр PC (R15). Походу тут без ассемблера не обойтись. Прошу помощи в реализации кода. Спасибо!
ViKo
А указатель на функцию не то?

Danis
Цитата(ViKo @ Nov 28 2011, 14:25) *
А указатель на функцию не то?


Думаю нет.
Flexz
Вам нужно сделать переход по адресу без модификации стека?
Если же на стек наплевать, то лучше сделать именно через указатель на фукнцию.
Danis
Цитата(Flexz @ Nov 28 2011, 15:54) *
Вам нужно сделать переход по адресу без модификации стека?
Если же на стек наплевать, то лучше сделать именно через указатель на фукнцию.


Немного конкретизирую. У меня в микроконтроллере два проекта.
Первый – загрузчик, располагается на последних страницах flash.
Второй – обновляемая программа (рабочая), расположена выше загрузчика.
После старта контроллера, программа попадает сразу в загрузчик. Последний проверяет, если нет подключения к ПК по USB, то нужно перепрыгнуть наверх, где расположена рабочая программа.
Для этого мне нужно как минимум инициализировать регистр вершины стека и записать значение перехода в программный счетчик.
Под отладкой, вручную забивал эти регистры – все работает на ”ура”.
borman11
Вот пример из бутлоадера Flash Magic
Код
void execute_user_code(void)
{
    void (*user_code_entry)(void);
    user_code_entry = (void(*)(void)) USER_FLASH_START;
    user_code_entry();
}
Danis
Цитата(borman11 @ Nov 28 2011, 21:56) *
Вот пример из бутлоадера Flash Magic
.....


подправил под себя:

unsigned int Data = *(u32*)(0x08000804);
void (*user_code_entry)(void);
user_code_entry = (void(*)(void))Data;
user_code_entry();


Да, работает (”перепрыгивает”), спасибо. Но мы тут просто ”тупо” перепрыгнули адрес (Инструкция BLX).
Но как быть с регистром R13(SP), полагаю, для правильной дальнейшей работы его тоже надо инициализировать значением из ячейки 0x08000800?
ViKo
Цитата(Danis @ Nov 29 2011, 09:42) *
Но мы тут просто "тупо” перепрыгнули адрес (Инструкция BLX).

"Тупо перепрыгнуть" была бы команда B, а здесь Branch with link and change state.
Вы занесли адрес возврата в LR. А стек при чем? Разве он чем-то забит?
Danis
Цитата(ViKo @ Nov 29 2011, 10:43) *
А стек при чем? Разве он чем-то забит?


Я ведь с одного проекта на другой перепрыгиваю. Разве можно оставить без инициализации SP?
ViKo
Цитата(Danis @ Nov 29 2011, 12:05) *
Я ведь с одного проекта на другой перепрыгиваю. Разве можно оставить без инициализации SP?

Так он же останется прежним. Если стек очищен, значит, указатель будет указывать на начало стека.
shreck
У меня загрузчик прыгает на основное приложение так (основа - примеры от ST):
Код
// Адрес начала основного приложения.
#define APLICATION_ADDRESS                  0x08003000

//------------------------------------------------------------------------------
// Запуск основного приложения, если оно зашито. Иначе возврат из функции.
void run_app_if()
{
    typedef  void (*pFunction)(void);
    pFunction Jump_To_Application;
    uint32_t JumpAddress;
    
    if (((*(__IO uint32_t*)APLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
    {
        // Jump to user application
        JumpAddress = *(__IO uint32_t*) (APLICATION_ADDRESS + 4);
        Jump_To_Application = (pFunction) JumpAddress;
        // Initialize user application's Stack Pointer
        __set_MSP(*(__IO uint32_t*) APLICATION_ADDRESS);
        Jump_To_Application();
    }
}
Danis
Цитата(shreck @ Nov 29 2011, 13:15) *
У меня загрузчик прыгает на основное приложение так (основа - примеры от ST):



Вот так все ОК пулучилось!

Код перехода из загрузчика в приложение (проверки на его наличие и целостность опущены):

unsigned int Data = *(u32*)(0x08000804);
void (*user_code_entry)(void);
user_code_entry = (void(*)(void))Data;
__set_MSP(*(__IO uint32_t*) 0x08000800);
user_code_entry();

shreck, отлично! Спасибо за подсказки.
ViKo, borman11, Flexz большое спасибо. Выручили!
toweroff
подниму вопрос по стеку еще раз, теперь для NXP, у которых нет __set_MSP()
итак, есть бут, есть пара вещей в оперативке и во флеше, которая должна остаться для приложения
ему (приложению) оставляются ссылки на все это дело

Из приложения вся инициализация пока убрана. Оно будет работать в своей области адресов, но может вызывать некоторые функции бута и обращаться к переменным (все адреса - в той таблице, приложение адрес таблицы знает)

Скажите, что так или не так

1. Вектора прерываний. Бут инициализирует таблицу в RAM. Приложение, если нужно, поменяет на свои
2. Тот же стек - в приложении активно пользоваться не будет (не выйдет за пределы, обозначенные бутом). Стоит ли менять? Если да, то как? (просто прочитал ветку и задумался, может там есть какие-то камни подводные?)
3. Сишные либы. Ну тут долго жевали не так далеко на форуме, решили, что лучше те же самые либы оставить как буту - бутово, приложению - приложенево
4. ....... Возможно, по ходу возникнет

Спасибо
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.