Значение контрольной суммы LPC4088 для большого пальца?

В руководстве пользователя LPC4088 (стр. 876) мы можем прочитал, что микроконтроллер LPC4088 имеет действительно необычную процедуру запуска:

введите здесь описание изображения

Это выглядит как полная ерунда, и мне нужен кто-то, кто поможет мне разобраться... В мире ARM я бессчетное количество раз слышал, что векторную таблицу можно представить так:

reset:                  b _start
undefined:              b undefined
software_interrupt:     b software_interrupt
prefetch_abort:         b prefetch_abort
data_abort:             b data_abort
                        nop
interrupt_request:      b interrupt_request
fast_interrupt_request: b fast_interrupt_request

точно в месте 0x00000000 в моем двоичном файле, но зачем нам это делать, если это место при загрузке затенено векторной таблицей загрузочного ПЗУ, которую даже нельзя изменить, поскольку она доступна только для чтения?! Итак, где мы можем разместить нашу собственную таблицу векторов? Я думал о том, чтобы поместить его в 0x1FFF0000, чтобы он был перенесен в местоположение 0x00000000 при сбросе, но не могу этого сделать из-за области только для чтения...

Теперь ко второй части. ARM ожидает найти ровно 8 векторов в 0x00000000, а при сбросе загрузочного ПЗУ проверяет, равна ли сумма 8 векторов нулю, и только если это верно, выполняется пользовательский код. Чтобы пройти эту проверку, нам нужно суммировать первые 7 векторов и сохранить их дополнение до 2 к последнему вектору, который является вектором для быстрых запросов на прерывание, находящихся в 0x0000001C. Ну, это верно только в том случае, если ваш код выровнен по 4 байтам (кодировка ARM), но все еще верно, если ваш код выровнен по 2 байтам (кодировка Thumb), что имеет место со всеми ядрами Cortex-M4, которые могут выполнять только кодировку Thumb коды операций... Так почему же они прямо упомянули, что дополнение 2 к сумме должно быть равно 0x0000001C, если это никогда не сработает с Cortex-M4. Является ли 0x0000000E правильным адресом для сохранения дополнения 2?

И третья часть. Зачем загрузочному ПЗУ проверять, равна ли сумма первых 8 векторов нулю, если они уже находятся в загрузочном ПЗУ?! И доступны только для чтения!

Ты видишь, что здесь что-то странное? Мне нужно, чтобы кто-нибудь объяснил мне неясности в трех предыдущих абзацах...


person 71GA    schedule 07.02.2018    source источник
comment
дело не в большом пальце, а в коре головного мозга.   -  person old_timer    schedule 07.02.2018


Ответы (1)


вам нужно прочитать документацию по руке, а также документацию по nxp. Ядра, отличные от cortex-m, загружаются иначе, чем ядра cortex-m, в которых вы постоянно застреваете.

Cortex m задокументирован в armv7m ARM ARM (справочное руководство по архитектуре). Он основан на ВЕКТОРАХ, а не на ИНСТРУКЦИЯХ. Адрес обработчику, а не инструкция, как в полноразмерных ядрах рук. Исключение 7 задокументировано как зарезервированное (для mcus на базе ARM7TDMI от них это был зарезервированный вектор, который они использовали и для этой контрольной суммы). В зависимости от используемого ядра руки они ожидают 144 или 272 (исключения плюс до 128 или 256 прерываний в зависимости от того, что поддерживает ядро).

(обратите внимание, что процессор aarch64, armv8 в 64-битном режиме также загружается иначе, чем традиционный полноразмерный 32-битный процессор arm, даже большая таблица).

Эта вещь с контрольной суммой является классической NXP и имеет смысл, нет причин запускать в стертую или неправильно подготовленную флэш-память и кирпич или зависание.

.cpu cortex-m0
.thumb
.thumb_func
.globl _start
_start:
.word 0x20001000 @ 0 SP load
.word reset @ 1 Reset
.word hang  @ 2 NMI
.word hang  @ 3 HardFault
.word hang  @ 4 MemManage
.word hang  @ 5 BusFault
.word hang  @ 6 UsageFault
.word 0x00000000 @ 7 Reserved

.thumb_func
hang: b hang
.thumb_func
reset:
    b hang

который дает:

Disassembly of section .text:

00000000 <_start>:
   0:   20001000    andcs   r1, r0, r0
   4:   00000023    andeq   r0, r0, r3, lsr #32
   8:   00000021    andeq   r0, r0, r1, lsr #32
   c:   00000021    andeq   r0, r0, r1, lsr #32
  10:   00000021    andeq   r0, r0, r1, lsr #32
  14:   00000021    andeq   r0, r0, r1, lsr #32
  18:   00000021    andeq   r0, r0, r1, lsr #32
  1c:   00000000    andeq   r0, r0, r0

00000020 <hang>:
  20:   e7fe        b.n 20 <hang>

00000022 <reset>:
  22:   e7fd        b.n 20 <hang>

теперь создайте специальный инструмент, который вычисляет контрольную сумму и добавляет ее в двоичный файл.

Глядя на приведенную выше программу как на слова, это программа:

0x20001000
0x00000023
0x00000021
0x00000021
0x00000021
0x00000021
0x00000021
0xDFFFEF38
0xE7FDE7FE

и если вы прошьете его, загрузчик должен быть доволен и позволить ему работать.

Теперь, если предположить, что контрольная сумма основана на словах, если она основана на байтах, вам понадобится другое число.

99% программирования на «голом металле» — это чтение и исследование. Если у вас уже был создан бинарный файл от них или вы использовали песочницу, которая поддерживает этот процессор или семейство, вы можете изучить созданный бинарный файл и посмотреть, как все это работает. Или посмотрите чьи-то примеры на github или блог, чтобы увидеть, как это работает. Они задокументировали это, и они использовали эту схему уже много лет, прежде чем они были NXP, так что ничего действительно нового ... Теперь это контрольная сумма на основе слов или байтов, документация подразумевает, что она основана на словах, и это имеет больше смысла. но простой эксперимент и / или просмотр двоичных файлов, созданных в песочнице, решил бы это.

Как я это сделал для этого ответа.

#include <stdio.h>
unsigned int data[8]=
{
0x20001000,
0x00000023,
0x00000021,
0x00000021,
0x00000021,
0x00000021,
0x00000021,
0x00000000,
};
int main ( void )
{
    unsigned int ra;
    unsigned int rb;

    rb=0;
    for(ra=0;ra<7;ra++)
    {
        rb+=data[ra];
    }
    data[7]=(-rb);
    rb=0;
    for(ra=0;ra<8;ra++)
    {
        rb+=data[ra];
        printf("0x%08X 0x%08X\n",data[ra],rb);
    }
    return(0);
}

вывод:

0x20001000 0x20001000
0x00000023 0x20001023
0x00000021 0x20001044
0x00000021 0x20001065
0x00000021 0x20001086
0x00000021 0x200010A7
0x00000021 0x200010C8
0xDFFFEF38 0x00000000

затем вырезал и вставлял материал в ответ.

Как я делал это в прошлом, так это создание специальной утилиты, которую я вызываю из моего make-файла, которая работает с objcopied .bin-файлом и либо изменяет его, либо создает новый .bin-файл с примененной контрольной суммой. Вы должны быть в состоянии написать, что в 20-50 строках кода выберите свой любимый язык.

еще вопрос комментария:

.cpu cortex-m0
.thumb

.word one
.word two
.word three

.thumb_func
one:
    nop
two:
.thumb_func
three:
    nop

Disassembly of section .text:

00000000 <one-0xc>:
   0:   0000000d    andeq   r0, r0, sp
   4:   0000000e    andeq   r0, r0, lr
   8:   0000000f    andeq   r0, r0, pc

0000000c <one>:
   c:   46c0        nop         ; (mov r8, r8)

0000000e <three>:
   e:   46c0        nop         ; (mov r8, r8)

.thumb_func влияет на метку ПОСЛЕ...

person old_timer    schedule 07.02.2018
comment
Я загрузил вашу программу напрямую через MBED и смог подключиться к цели с помощью команды JLinkExe connect LPC4088. Так что это выглядит хорошо до сих пор. Как получилось, что это сработало даже без сохранения дополнения 2 в 0x1C? Я только что скомпилировал ваш исходный файл... - person 71GA; 07.02.2018
comment
Возможно, отладочный микроконтроллер добавил контрольную сумму по пути к демонстрационному микроконтроллеру. - person old_timer; 07.02.2018
comment
используйте свой отладчик, чтобы сбросить это адресное пространство и посмотреть, есть ли там ноль или что-то было добавлено - person old_timer; 07.02.2018
comment
и соответствует ли это значение, если оно не равно нулю, тому, которое я разместил здесь? - person old_timer; 07.02.2018
comment
Может быть, вы правы, и это сделал отладочный зонд ... Я сделал дамп своей прошивки изнутри JLinkExe, используя savebin flash.dump, 0x0, 0x24, я получил ответ: Opening binary file for writing... [flash.dump] Reading 36 bytes from addr 0x00000000 into file...O.K.. После проверки файла flash.dump вот что внутри: 00100020 23000000 21000000 21000000 21000000 21000000 21000000 38EFFFDF FEE7FDE7. Они написаны задом наперёд? Хм? - person 71GA; 07.02.2018
comment
приятно, и это даже значение, которое я вычислил. поэтому следующий шаг — не использовать виртуальный флэш-накопитель и войти через swd/jtag, но вам нужно вычислить контрольную сумму перед записью. должно быть альтернативное адресное пространство, которое флэш-память может быть прочитана, если загрузчик отображается, вы должны быть в состоянии подтвердить, даже если он не запускал ваш код, если он действительно записывал во флэш-память, разделите проблему пополам, действительно ли ваш отладчик пишет что-либо. - person old_timer; 07.02.2018
comment
ваш инструмент просто печатает их с заменой байтов. хотя это другой вопрос о вашем инструменте. если у вас есть недействительная флэш-память приложения, загрузчик должен быть сопоставлен с 0x0000, и он также должен иметь таблицу векторов, как выглядят его векторы с помощью вашего инструмента отладки. было бы очень грустно иметь байтовый обмен, но это случается. - person old_timer; 07.02.2018
comment
я предпочитаю не использовать флэш-программистов в инструментах, поскольку вы становитесь зависимыми от инструментов, я предпочитаю загружать программу на основе оперативной памяти, которая в прикладных программах флэш-памяти, как переносить или получать данные для флэш-памяти, различается. эти части могут иметь загрузчик, мы знаем, что они есть, и этот загрузчик может иметь uart или другой интерфейс, который не зависит от инструмента, который вы можете использовать. стоит изучить ваш инструмент, но помните, что если вы поменяете инструменты, правила могут измениться, и вам, возможно, придется начинать заново. - person old_timer; 07.02.2018
comment
или, если вы придерживаетесь этой доски, вы можете просто скопировать файл, не нужно вычислять контрольную сумму и т. Д. Примерно так же просто, как и получается. - person old_timer; 07.02.2018
comment
О да, теперь я вижу, как байты меняются местами... Похоже, мне придется искать другой шестнадцатеричный редактор! Не могли бы вы рассказать мне, как вы вычислили значение контрольной суммы 38EFFFDF? И еще... Когда вы разобрали свой файл .elf, я вижу, что векторная таблица выровнена по 4 байтам, а все, что после таблицы, выровнено по 2 байтам... Директива .thumb_func сделала это? Как? - person 71GA; 08.02.2018
comment
О, я уже нашел ответ в одном из ваших ответов: stackoverflow.com/questions/4423211/ БОЛЬШАЯ РАБОТА! - person 71GA; 08.02.2018
comment
.word для сборки arm gnu означает слово 32 бита, и инструменты gnu каким-то образом оставляют информацию в эльфе, чтобы знать это. 16-битные элементы являются инструкциями для большого пальца из-за .thumb в верхней части, а ассемблер и т. д. оставляют информацию в эльфе, чтобы указать это, чтобы у дизассемблера был шанс. thumb_func - это самый дешевый способ в gas, который я знаю, чтобы сообщить gas, что эта метка является функцией, и это указывает на адрес с единицей, посмотрите, как таблица имеет адрес или с единицей, как это должно быть (я думаю некоторые ядра cortex-m работают, если младший бит не установлен). - person old_timer; 08.02.2018
comment
удалите один из этих thumb_funcs, и вы увидите, что метка не помечена как функция, и, следовательно, ее адрес не имеет установленного lsbit. некоторые люди пытаются решить эту проблему, помещая .word reset+1, потому что, несмотря на то, что в документации .word reset|1 не работает, если кто-то получает метку правильно, то +1 теперь делает ее неправильной, если вы можете заставить инструмент принимать |1 ( или красный с 1), затем пометьте правильно или неправильно, это работает. - person old_timer; 08.02.2018
comment
бывают случаи, когда вам нужен .align в вашем коде. у вас может быть какая-то сборка, а затем .word, если сборка приводит к хорошему выравниванию .word, добавьте nop, и он может или не может быть для вас, зависит от инструмента, добавление .align может не повредить в тех ситуации. Хуже всего, если инструмент помещает .word на вас без выравнивания. но код, как показано, РАЗБОРКА получает правильные размеры и выравнивание, потому что инструменты gnu оставляют для себя хлебные крошки, обратите внимание, что он дизассемблировал эти элементы .word как инструкции для рук, которых нет, что может сбить людей с толку. - person old_timer; 08.02.2018
comment
дизассемблер при таком использовании мощный, особенно для рук и других, которые очень выровнены (не так сильно x86), но он пытается дизассемблировать текст и все остальное. readelf также полезен, но я просто использую objdump и знаю, на что смотреть, а что игнорировать. - person old_timer; 08.02.2018
comment
Я настоятельно рекомендую, когда вы создаете новый make-файл или сценарий сборки или что-то еще, если нет другого времени, используйте дизассемблер или какой-либо другой инструмент, чтобы убедиться, что у вас есть таблица векторов в нужном месте и векторы правильные, отлаживая плохую сборку с кодом /data в таблице может занять очень много времени и может заблокировать вашу доску, если у вас нет способа разблокировать ее. занимает несколько секунд каждый новый проект... - person old_timer; 08.02.2018
comment
Спасибо за уделенное время. Просто сейчас немного больше путаницы. Например, почему вы разместили сначала .thumb_func перед _start:, а не после него? Это не имело бы значения, верно? И почему вы начинаете свою таблицу векторов исключений с вектора, указывающего на середину периферийной SRAM (0x20001000), а не основной SRAM, простирающейся от 0x10000000 до 0x1000FFFF? Был ли это просто выбор или предосторожность? - person 71GA; 08.02.2018
comment
cortex-ms обычно имеет оперативную память по адресу 0x20000000, но, возможно, у вас исключение или, возможно, это зависит от поставщика. Я должен был бы проверить ваш лист данных еще раз. Я использую 0x1000, потому что во многих частях их много, поэтому, если я вырезаю и вставляю пример несколько раз или между частями, мне не нужно постоянно менять это число до тех пор, пока/если я не использую больше этого. - person old_timer; 08.02.2018
comment
Я думаю, что .thumb_func работает со следующей найденной меткой, поэтому она должна быть до метки, а не после. на самом деле _start на самом деле не нужен, так как мы не используем операционную систему, на самом деле _start вообще не нужен, но есть бэкэнд qemu, который выбирает, как он запускался на основе адреса входа, поэтому, возможно, этот код был получен из него. в общем, хотя я думаю, что это должно быть перед ярлыком, на котором вы хотите его использовать. - person old_timer; 08.02.2018
comment
с вашей стороны в главе 2 память начинается с 0x20000000, что типично для cortex-m (возможно, требуется как часть дизайна). - person old_timer; 08.02.2018
comment
LPC408x/407x содержит до 96 КБ встроенной статической оперативной памяти. До 64 КБ SRAM, доступной для ЦП и контроллера прямого доступа к памяти общего назначения, находится на высокоскоростной шине. До 32 КБ SRAM предоставляется в двух дополнительных блоках SRAM по 16 КБ для использования в основном для периферийных данных. Когда присутствуют обе SRAM, они расположены на отдельных подчиненных портах на многослойной матрице AHB. - person old_timer; 08.02.2018
comment
так что не знаю, что они подразумевают под статической оперативной памятью и чем она отличается от SRAM? Означает ли это, что на него не влияет теплый сброс? не знаю... - person old_timer; 08.02.2018
comment
Спасибо! =) Сейчас я копаюсь в общем руководстве пользователя Cortex-M4, а не в техническом справочном руководстве Cortex-M4. У меня был не тот документ, и я не смог найти там много информации... Непонятно, что читать в первую очередь, но теперь я думаю, что знаю... Вы дали мне фору. Много вреда нанес учебник (bravegnu.org/gnu-eprog), где автор очень наивен когда его код работает в симуляторе QEMU... Ну, этот код никогда не запустится на настоящем Cortex-M4, поскольку он использует инструкции в таблице векторов, а не только векторы (адреса)... Было приятно играть с QEMU, но реально сделка намного лучше! - person 71GA; 08.02.2018
comment
поставщик чипа (nxp) скажет, что у него есть cortex-m4, поэтому вы переходите к техническому справочному руководству cortex-m4 от arm, там есть хорошая информация, начиная с cortex-m4, использующего архитектуру armv7-m, так что вы получаете Справочник по архитектуре armv7-m. Это два ваших основных документа по рукам. Иногда у поставщика есть их версии, и я думаю, что есть справочник программистов, который, похоже, ведет людей в неправильном направлении, так что остерегайтесь этого, вероятно, тоже содержит хорошую информацию. тогда есть документ поставщиков чипов, который вы нашли... - person old_timer; 08.02.2018