Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ISP бутлоaдер
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
kolisnichenko_r
МК LPC1549 – прошивка записывается (ISP бутлоaдер по CAN сети) и запускается. Нужно считать Flash для проверки. Читаю – в первой странице не то что должно быть. Защита от чтения не установлена.
Докопался до того места что для считывания первых 512 байт Flash памяти нужно в ISP загрузить кусочек кода который мапит Flash на нулевой адрес. То есть нужно в регистр SYSMEMREMAP (0x40074000 адрес) записать значение 0x02. Как это сделать?
esaulenka
Ох, как-то замороченно у них получилось...
Оставили б альтернативные адреса (например, флеш живёт по адресу 0x0800 0000, по спец-команде дополнительно мапится на 0), и всем было б хорошо...

Писать/читать регистры периферии можно командами "write to ram" и "read memory".
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 10:27) *
Ох, как-то замороченно у них получилось...
Оставили б альтернативные адреса (например, флеш живёт по адресу 0x0800 0000, по спец-команде дополнительно мапится на 0), и всем было б хорошо...

Писать/читать регистры периферии можно командами "write to ram" и "read memory".

RAM этого МК занимает адресное пространство от 0х02000000 до 0х02009000, а SYSMEMREMAP расположен в 0x40074000. "write to ram" не сработает.

Подглядел в дизассемблере компилятора:
Код
//LPC_SYSCON->SYSMEMREMAP = 0x2; //change memory map 0x2
00001d5e:   ldr r3, [pc, #148]    ; (0x1df4 <main+172>)
00001d60:   movs r2, #2
00001d62:   str r2, [r3, #0]

Наверное, можно применить следующую последовательность команд:
Код
LDR     R0, =0x40074000; Прочитать в R0 значение регистра SYSMEMREMAP, 0x40074000 адрес
MOV     R1, #2; Загрузить в R1 значение 0x2 которое нужно записать в регистр SYSMEMREMAP        
STR     R1, [R0]; Записать значение из R1 в регистр по адресу из R0    
BX      LR; Возрат - переход по адресу, записанному в регистре LR (R14)

Как считаете?
Еще остается вопрос как из ассемблера перевести в последовательность цифр.
esaulenka
Цитата(kolisnichenko_r @ Mar 18 2016, 11:21) *
RAM этого МК занимает адресное пространство от 0х02000000 до 0х02009000, а SYSMEMREMAP расположен в 0x40074000. "write to ram" не сработает.

Почему же не сработает?
Это просто инструкция ядру "запиши по адресу", дальше пусть все эти bus matrix думают, к какому именно устройству Вы хотели обратится.

Можно, конечно, написать микро-программку, загрузить её в ОЗУ, сказать Go(нужный адрес). Только мне неочевидно, что произойдёт после завершения этой программы. Подозреваю, обратно в загрузчик надо возвращаться принудительно.
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 11:54) *
Почему же не сработает?
Это просто инструкция ядру "запиши по адресу", дальше пусть все эти bus matrix думают, к какому именно устройству Вы хотели обратится.

Можно, конечно, написать микро-программку, загрузить её в ОЗУ, сказать Go(нужный адрес). Только мне неочевидно, что произойдёт после завершения этой программы. Подозреваю, обратно в загрузчик надо возвращаться принудительно.

Загружал последовательность из темы http://electronix.ru/forum/index.php?s=&am...t&p=1325093, изменял адрес на 0x40074000. В загрузчик возвращается но после этого читает не понятно что во всех секторах Flash.
С самой микро-программкой вроде понятно, даже на ассемблере можно на ваять, а перевести в числа как? Никогда такого не делал. С какой стороны подступиться?
esaulenka
Я тоже никогда не делал.
Пришлось научиться :-)

Берём gcc.
Пишем:
Код
void remap_flash ()
{
    asm volatile(
        "mov  r0, #(0x40074000 & 0xFFFF)    \r\n"
        "movt r0, #(0x40074000 >> 16)        \r\n"
        "movs r1, #2                        \r\n"
        "str r1, [r0]                        \r\n"
      );
}

Вызываем из main().
Смотрим листинг:
Код
080103d8 <remap_flash()>:
_Z11remap_flashv():
... main.cpp:25
    asm volatile(
        "mov  r0, #(0x40074000 & 0xFFFF)    \r\n"
        "movt r0, #(0x40074000 >> 16)        \r\n"
        "movs r1, #2                        \r\n"
        "str r1, [r0]                        \r\n"
      );
80103d8:    f44f 4080     mov.w    r0, #16384; 0x4000
80103dc:    f2c4 0007     movt    r0, #16391; 0x4007
80103e0:    2102          movs    r1, #2
80103e2:    6001          str    r1, [r0, #0]
80103e4:    4770          bx    lr
80103e6:    bf00          nop
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 13:17) *
Код
        "mov  r0, #(0x40074000 & 0xFFFF)    \r\n"
        "movt r0, #(0x40074000 >> 16)        \r\n"

Спасибо за науку.
А зачем разбивать запись адреса на две команды?
esaulenka
Да это просто :-)
Длина команды thumb2 - 16 бит или 32. 32-битная константа напрямую в эту команду не влезает (нужно же место под код самой команды).
Можно положить константу рядом, и ссылаться на неё (что-то вроде LDR r0, [pc, #смещение-до константы]); компилятор так и делает.
Но руками проще загрузить в регистр за два раза, благо у кортексов команда MOVT сделана, похоже, специально для этого.
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 14:27) *
Да это просто :-)
Длина команды thumb2 - 16 бит или 32. 32-битная константа напрямую в эту команду не влезает (нужно же место под код самой команды).
Можно положить константу рядом, и ссылаться на неё (что-то вроде LDR r0, [pc, #смещение-до константы]); компилятор так и делает.
Но руками проще загрузить в регистр за два раза, благо у кортексов команда MOVT сделана, похоже, специально для этого.

Да, нужно ассемблер под читать.

Скормил в RAM последовательность:
0x4F 0xF4 0x80 0x40 0xC4 0xF2 0x07 0x00 0x02 0x21 0x01 0x60 0x70 0x47
Все равно не читает.
Делаю по шагам:
1) Установка адреса для записи в RAM 0x02001000:
0x23 0x15 0x50 0x00 0x00 0x10 0x00 0x02
2) Команда записи данных в RAM:
0x21 0x50 0x1F 0x01
3) Запись данных в RAM 7 байт:
0x00 0x4F 0xF4 0x08 0x40 0xC4 0xF2 0x07
4) Запись данных в RAM 7 байт:
0x11 0x00 0x02 0x21 0x01 0x60 0x70 0x47
5) Задание адреса входа в программу (МК) в RAM 0x02001000:
0x23 0x70 0x50 0x01 0x00 0x10 0x00 0x02
6) Старт МК («Go»):
0x2F 0x51 0x1F 0x01 0x01 0x00 0x00 0x00

Ошибок не возвращает, но и в первой странице не то.
Правильно ли я интерпретировал последовательность микропрограммки?
esaulenka
Не знаю.
Сделайте то же самое, но под отладчиком:

Код
char remap_flash[] = { 0x00, 0x4F  ... };

( (void (*)(void)) remap_flash) ();
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 15:57) *
Не знаю.
Сделайте то же самое, но под отладчиком:

Код
char remap_flash[] = { 0x00, 0x4F  ... };

( (void (*)(void)) remap_flash) ();

Отладчик отрабатывает последовательность: 0xF4, 0x4F, 0x40, 0x80, 0xF2, 0xC4, 0x00, 0x07, 0x21, 0x02, 0x60, 0x01, 0x47, 0x70
и регистр SYSMEMREMAP изменяет значение на 0х2.
Посылаю эту же последовательность в МК - он ее принимает, а потом перестает отвечать, наверное нужно вернуть его в режим ISP.
esaulenka
Да, кстати. Загрузчик понимает, что код - в thumb mode, и program counter должен быть нечётным?
Попробуйте сделать GO на адрес 0x02001001
kolisnichenko_r
Цитата(esaulenka @ Mar 18 2016, 16:56) *
Да, кстати. Загрузчик понимает, что код - в thumb mode, и program counter должен быть нечётным?
Попробуйте сделать GO на адрес 0x02001001

Проделал - МК отвечает: ошибка адреса.

Для возврата в ISP нужна команда Chip_IAP_ReinvokeISP(), а она опять изменит в SYSMEMREMAP значение на 0х0.
Круг какой-то.
Как же люди делают?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.