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

Cortex-M0
Тогда нужно:

1) Располагать (линковать) загрузчик с адреса 0x08000000, чтобы он мог продолжать работать после ремапа.

2) Располагать (линковать) приложение с адреса 0x0800хххх, чтобы онo могло работать после ремапа.

2) Копировать вектора приложения в начало ОЗУ. У приложения должно быть "откушено" начало ОЗУ под это дело в скрипте линкера.

3) Из векторов приложения брать адрес начала стека и прописывать его в MSP

4) Делать ремап (SYSCFG, биты MEM_MODE)

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

 

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


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

Если буту прерывания не нужно, то можете посмотреть пример NXP (secondary bootloader)

 

В этом примере предлагают использовать ассемблерные вставки, добавляю их в main() Бутлоадера:

 

__asm volatile("ldr r0, =0x103C");

__asm volatile("ldr r0, [r0]");

__asm volatile("mov pc, r0");

 

Компиллирую проект, выдает ошибку:

aplication\main.c(38): error: #1113: Inline assembler not permitted when generating Thumb code

 

Добавляю в настройках проекта --arm.

Появляется ошибка:

main.c: Error: C3006E: specified processor or architecture does not support ARM instructions

 

 

Тогда нужно:

1) Располагать (линковать) загрузчик с адреса 0x08000000, чтобы он мог продолжать работать после ремапа.

2) Располагать (линковать) приложение с адреса 0x0800хххх, чтобы онo могло работать после ремапа.

2) Копировать вектора приложения в начало ОЗУ. У приложения должно быть "откушено" начало ОЗУ под это дело в скрипте линкера.

3) Из векторов приложения брать адрес начала стека и прописывать его в MSP

4) Делать ремап (SYSCFG, биты MEM_MODE)

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

 

1,2) Flash-память микроконтроллера lpc11c24 - 0x0000 0000 - 0x0000 8000

RAM-память - 0х1000 0000 - 0х1000 2000

Адреса 0x08000000 у меня нет.

Если загрузчик распологаю не по адресу 0х0000 0000, то у меня МК не стартует.

 

2) копировать с помощью ассемблерных вставок из NXP примера "secondary bootloader"? Постом ниже я написал о затруднениях, с которыми столкнулся при их использовании.

 

3,4) также выподняется ассемблерными вставками?

 

 

 

 

 

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


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

Компиллирую проект, выдает ошибку:
С кейлом не работаю, не подскажу. Пусть другие участники помогутю

1,2) Flash-память микроконтроллера lpc11c24
А название ветки - STM32 bootloader. Невнимательно читал ваше первое сообщение и даю советы по STM32F0xx. :laughing:

Для LPC11 ремапятся первые 512 байт. Соответственно смотрите по ссылке от _Артем_а - там я приводил кусок запуска приложения для LPC11

2) копировать с помощью ассемблерных вставок из NXP примера "secondary bootloader"? Постом ниже я написал о затруднениях, с которыми столкнулся при их использовании.

 

3,4) также выподняется ассемблерными вставками?

2 - можно и ассемблером, но зачем? Можно сделать и на С/С++ при помощи цикла и указателей либо библиотечной функцией memcpy()

3) да, ассемблерная вставка либо функция из CMSIS, которая тоже на ассемблерной вставке строится.

4) Обычная сишная запись в регистр. Для LPC это будет регистр SYSMEMREMAP

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


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

2) а если размещать вектор прерываний не в RAM, а во flash по адресу 0х0000 2000 (сюда у меня рабочая программа линкуется), с помощью встроенных IAP-команд, которые позволяют записывать во флеш страницами по 256 байт?

Нужно ли будет в таком случае делать Remap?

3) Не помните названия функции?

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


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

2) а если размещать вектор прерываний не в RAM, а во flash по адресу 0х0000 2000
Разместить вектора вы можете где угодно, но вот процессор читает их с адреса 0x00000000. И никаких способов считывать их из других адресов у Cortex-M0 не предусмотрено (у M3 для этого есть регистр VTOR). Поэтому разработчики процессоров идут на хитрость - делают отражение (remap) на эти адреса других регионов памяти, например RAM. После ремапа вы кладете какие-то данные в начало RAM, а процессор их "видит" не только по "родным" адресам в RAM, но и в начале флеша. И таких мест, которые могут быть отражены на начало адресного пространства всего два - начало ОЗУ и начало ПЗУ со встроенным загрузчиком (ISP). Эти места прибиты гвоздями к своим адресам разработчиками процессора.

3) Не помните названия функции?
Нет, я не использую CMSIS (только заголовочный файл с описанием адресов регистров). Поищите поиском по файлам, ключевое слово "MSP" вы уже знаете. Или обратитесь в техподдержку Кейла -они должны быстро отвечать на вопросы покупателей своего продукта.

 

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


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

Т.е., когда я заливаю "Загрузчик" по адресу 0х0000 0000 и "Рабочую программу" по адресу 0х0000 2000 обе программы обращаются к одной и той же таблице векторов, которая расположена по адресу 0х0000 0000. Из-за этого "Рабочая программа" запуститься не может, потому что в ней находятся данные "Загрузчика".

Я правильно понял суть проблемы?

 

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


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

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

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


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

А как такое решение проблемы:

Проект №1 - "Загрузчик"

Проект №2 - "Рабочая программа"

 

После того как мы их скомпилировали, открыть HEX-файлы обоих проектов.

В ручную заменить строки в НЕХ-файле "Загрузчика", соответствующие таблице векторов прерываний на аналогичные строки из НЕХ-файла "Рабочей программы" не трогая только первые две ячейки: main stack pointer и reset vector.

 

И поскольку в моем "Загрузчике" не используются прерывания, то передав управление "Рабочей программе" та запустится.

 

Сработает?

 

А как такое решение проблемы:

Проект №1 - "Загрузчик"

Проект №2 - "Рабочая программа"

 

После того как мы их скомпилировали, открыть HEX-файлы обоих проектов.

В ручную заменить строки в НЕХ-файле "Загрузчика", соответствующие таблице векторов прерываний на аналогичные строки из НЕХ-файла "Рабочей программы" не трогая только первые две ячейки: main stack pointer и reset vector.

 

И поскольку в моем "Загрузчике" не используются прерывания, то передав управление "Рабочей программе" та запустится.

 

Сработает?

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


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

Если Вы в загрузчике не используете прерывания - сделайте как в примере от NXP (secondary bootloader)

В прерываниях загрузчика сделайте редирект на прерывания приложения. Как-то так можно:

(для загрузчика размером 4кб(0x1000) )

 

#define BOOTLOADER_SIZE 0x1000

 

#define redirect(address) unsigned long pc = *(unsigned long*)(address) + (BOOTLOADER_SIZE); void (*redirect_handler)(void) = (void(*)(void))pc;\ redirect_handler();

 

....

void CT16B0_IRQHandler(void) { redirect(0x1080); }

void CT16B1_IRQHandler(void) { redirect(0x1084); }

void CT32B0_IRQHandler(void) { redirect(0x1088); }

.....

Изменено пользователем Alex19

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


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

После того как мы их скомпилировали, открыть HEX-файлы обоих проектов.

В ручную заменить строки в НЕХ-файле "Загрузчика", соответствующие таблице векторов прерываний на аналогичные строки из НЕХ-файла "Рабочей программы" не трогая только первые две ячейки: main stack pointer и reset vector.

Давайте думать дальше. Вы доработали рабочую программу и ее обработчики прерываний оказались по другим адресам. Вам снова надо брать обе прошивики, снова копировать строки HEX-файлов, программировать уже обновленный загрузчик. Тогда какой в нем смысл, если его надо править и заливать программатором перед каждым обновлением приложения?

В чем проблема? Вам жалко 256 байт ОЗУ (а реально меньше, ибо не вся таблица используется)?

 

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


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

Давайте думать дальше. Вы доработали рабочую программу и ее обработчики прерываний оказались по другим адресам. Вам снова надо брать обе прошивики, снова копировать строки HEX-файлов, программировать уже обновленный загрузчик. Тогда какой в нем смысл, если его надо править и заливать программатором перед каждым обновлением приложения?

В чем проблема? Вам жалко 256 байт ОЗУ (а реально меньше, ибо не вся таблица используется)?

Пытаюсь сделать с помощью Ремапа, не могу понять в чем дело. Решил идти от простого к сложному.

 

1)Самое простое в ручную из одного HEX-файла скопировать данные по адресам 0х09-0хС0 (по этим адресам располагается таблица векторов. Не трогаю лишь два первых вектора 0х00 - 0х08). Получилось "Рабочая программа" запустилась.

 

2) Перешел к более сложному - копирую файлы 0х00 - 0х08 (MSP и Reset handler) программно с помощью чего осуществляю прыжок в "Рабочую программу" и она запускается, если не использует прерываний:

 

#include "LPC11xx.h"

#include "core_cm0.h"

#include "system_LPC11xx.h"

 

__ASM void __jump_( )

{

ldr r0, =0x1000

ldr r0, [r0]

mov sp, r0

 

ldr r0, =0x1004

ldr r0, [r0]

mov pc, r0

}

 

nt main(void)

{

SystemInit();

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

 

__jump_( );

 

while(1);

}

 

3)Перехожу к более сложному - программно копирую всю таблицу прерываний - 0х00 - 0хС0.

Текст программы:

 

#include "LPC11xx.h"

#include "core_cm0.h"

#include "system_LPC11xx.h"

 

__ASM void __jump_( )

{

ldr r0, =0x1000

ldr r0, [r0]

mov sp, r0

 

ldr r0, =0x1004

ldr r0, [r0]

mov pc, r0

 

ldr r0, =0x1008

ldr r0, [r0]

ldr r1, =0x0008

mov [r1], r0

 

ldr r0, =0x1008

ldr r0, [r0]

ldr r1, =0x0008

mov [r1], r0

 

......................

//здесь такие же наборы команд для других адресов

......................

 

ldr r0, =0x10BC

ldr r0, [r0]

ldr r1, =0x00BC

mov [r1], r0

 

 

}

 

int main(void)

{

SystemInit();

LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

 

__jump_( );

 

while(1);

}

 

И тут сталкиваюсь с затруднением - компилятор на строке "mov [r1], r0" выдает ошибку:

error: A1647E: Bad register name symbol, expected Integer register

В чем дело?

Эта команда же допускает копирование из РОН в память

 

 

 

 

 

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


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

Эта команда же допускает копирование из РОН в память
Если вы читаете из памяти командной ldr, то писать в нее логично командой str.

Но, мама дорогая! Почему на ассемблере, да еще и тупым copy-paste? Это, кажется, называется "индусский код"?

 

uint32_t const * pSrc = (uint32_t const *)0x1000;
uint32_t * pDst = (uint32_t const *)0x0000;
#define VECTORS_COUNT  64   // подставьте сколько нужно, включая указатель стека и reset handler
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
   *pDst++ = *pSrc++;

 

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


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

Если вы читаете из памяти командной ldr, то писать в нее логично командой str.

Но, мама дорогая! Почему на ассемблере, да еще и тупым copy-paste? Это, кажется, называется "индусский код"?

 

uint32_t const * pSrc = (uint32_t const *)0x1000;
uint32_t * pDst = (uint32_t const *)0x0000;
#define VECTORS_COUNT  64   // подставьте сколько нужно, включая указатель стека и reset handler
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
   *pDst++ = *pSrc++;

 

Индусский ли пиндосский ли...))

 

Ваш кусок кода не перепрыгивает в "Рабочую программу". Видимо на STM32 есть возможность напрямую писать во флеш (в lpc11xx это возможно только посредством специальных IAP команд)

Написанная мною тоже не пашет:

 

ldr r0, =0x1004 ; загружаем в r0 константу 0х1004

ldr r0, [r0] ; загружаем в r0 содержимое по адресу 0х1004

ldr r1, =0x0004 ; загружаем в r0 константу 0х0004

str r0, [r1] ; загружаем значение r0 в адрес r1

 

 

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


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

Видимо на STM32 есть возможность напрямую писать во флеш
Вы и себя запутали и я просто перенес на С ваш код с некоторой оптимизацией. Не нужно писать во флеш. И не нуждно копировать в адрес 0. Надо копировать в начало ОЗУ. И потом ремапом подставлять эту область ОЗУ на нулевые адреса:

 

uint32_t const * pSrc = (uint32_t const *)0x00001000;  // начало приложения
uint32_t * pDst = (uint32_t *)0x10000000;                 // начало ОЗУ
#define VECTORS_COUNT  64   // подставьте сколько нужно, включая указатель стека и reset handler
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
   *pDst++ = *pSrc++;
// далее надо загрузить указатель стека.
не_знаю_как_это_сделать_в_кейле(*(uint32_t const *)0x00001000);
//
LPC_SYSCON->SYSMEMREMAP = 1;  // remap to ram
void (*Application)();
Application = *(void (**)())0x10000004;
Application();

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


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

Вы и себя запутали и я просто перенес на С ваш код с некоторой оптимизацией. Не нужно писать во флеш. И не нуждно копировать в адрес 0. Надо копировать в начало ОЗУ. И потом ремапом подставлять эту область ОЗУ на нулевые адреса:

 

uint32_t const * pSrc = (uint32_t const *)0x00001000;  // начало приложения
uint32_t * pDst = (uint32_t *)0x10000000;                 // начало ОЗУ
#define VECTORS_COUNT  64   // подставьте сколько нужно, включая указатель стека и reset handler
for(uint_fast8_t i = 0; i < VECTORS_COUNT; ++i)
   *pDst++ = *pSrc++;
// далее надо загрузить указатель стека.
не_знаю_как_это_сделать_в_кейле(*(uint32_t const *)0x00001000);
//
LPC_SYSCON->SYSMEMREMAP = 1;  // remap to ram
void (*Application)();
Application = *(void (**)())0x10000004;
Application();

 

Спасибо за пояснения)) Но с ремапом у меня нивкакую запускаться не хочет))

Продолжу с понедельника.

П.с. и все же есть возможность записи во флеш ассемблерными вставками?(Как запасной вариант, если ремап не запустится)

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


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

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

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

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

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

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

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

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

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

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