Практика использования mspdebug. Отладка без программы

На этот раз программный код для заливки в микроконтроллер нам не понадобится. Сегодня мы потренируемся читать-писать память. А поскольку MSP430 относится к машинкам Фон-Неймановского класса и его регистры периферийных устройств размещаются в едином адресном пространстве, то доступ к этим регистрам точно такой же как и к обычным ячейкам памяти.

И в самом деле, запись байта в память RAM ничем не отличается от записи байта в порт ввода/вывода. Тоже самое касается и чтения. Фокус состоит в том, что к порту обычно что-нибудь подключается, например светодиоды, кнопочки или другие компоненты.

Говоря метафорами, порт — это некая комната в большом здании. Комната имеет двери в общий коридор и имеет окно. Ядро микропроцессора общается с «комнатой» через двери, а внешний мир «смотрит» в комнату через окно.

Продолжая аналогию, можно сказать, что ячейка памяти — это кладовка с одной единственной дверью. Что в ней лежит, внешний мир знать не может. Только ядро процессора имеет право попасть в кладовку — что-то туда положить или взять.

Как я уже упоминал, если к порту микроконтроллера подключен светодиод, то записывая в порт определённые значения можно зажигать и гасить этот светодиод. А поскольку mspdebug действует со стороны ядра, то мы можем напрямую управлять светодиодом,  не прибегая к написанию программ и заливке кода во флешь-память.

В качестве подопытного кролика я буду использовать отладочную плату MSP-EXP430G2:

IMG_1005

На фото видно, что в сокете находится MSP430G3553. На самом деле, у меня там сейчас стоит MSP430F2001. Сейчас это не принципиально, в той части, с которой мы будем играться, микроконтроллеры полностью совпадают.

В качестве внешних устройств микроконтроллера на плате также установлены два светодиода и одна кнопка. Все они подключены к порту P1 по следующей схеме:

IMG_1009

Схема взята из одного моего старого проекта. На ней указаны задействованные биты порта (они не заштрихованы) и указаны направления линий (битов) — две линии на ввод и две на вывод. J5 — это джамперы, установленные на отладочной плате, они позволяют отключить светодиоды от микроконтроллера. Сигнал SMCLK — это тактовый сигнал для периферийных модулей микроконтроллера. Не обращайте на него внимания, он нам не нужен!

Я предполагаю, что вы уже знакомы с работой портов ввода-выводв и более-менее знаете назначение их регистров. Нас будут интересовать только три регистра P1IN, P1OUT и P1DIR. Подтяжки, прерывания, функции — это несколько более сложные вещи, работа с ними не даст наглядности наших действий (осязаемости).

Согласно описанию архитектуры микроконтроллера регистры портов располагаются по следующим адресам:

Адрес Регистр
0x0020 P1IN
0x0021 P1OUT
0x0022 P1DIR

Прежде чем мы включим светодиод, нужно заметить, что после сброса порт микроконтроллера сконфигурирован на ввою. Чтобы управлять светодиодами нужно перевести соответствующие линии (биты) порта на вывод. Поскольку у нас два светодиода, и они «сидят» на нулевом и шестом бите, то мы должны записать в регистр P1DIR следующее битовое значение:

0 1 0 0  0 0 0 1

Это число 0x41.

В ассемблере это делается командой

mov.b   #0x41, &0x0022

Если в проекте, который мы разрабатываем, подключены файлы описания регистров, то мы можем написать так:

mov.b   #0x41, &P1DIR

Заметьте, теперь нам не надо помнить адрес регистра порта.

На языке Си эта операция выглядит еще проще:

P1DIR = 0x41;

и компилируется в тот же самый код!

В свои проекты я обычно подключаю файл определения битов портов, который выглядит примерно так:

// Назначение линий портов
// Порт P1
#define LED_RED    (BIT0)
#define BUTTON     (BIT3)
#define SMCLK      (BIT4)
#define LED_GREEN  (BIT6)

Таким образом у меня отпадает необходимость даже «конструировать» (и совершать обидные ошибки!) hex-значения. Сравните с предыдущим вариантом:

P1DIR = (LED_GREEN + LED_RED);

— написано почти по-человечески! Это то, что называется самодокументированный код.

Однако, я слишком далеко ушёл от темы! Давайте же перейдём к практике!

Я предполагаю, что у вас уже mspdebug установлен и отладочная плата подключена. Запускаем mspdebug:

mspdebug.1

При запуске дебаггер вывалит в терминал довольно-таки много разной информации. Вы можете более детально её просмотреть, определённая польза от этого занятия есть, но я сейчас хотел бы продвинуться дальше.

Давайте переведем линии порта P1, к которым подключены светодиоды на вывод. Для этого нужно записать по адресу 0x0022 значение 0x41. Команда для записи называется mw (от memory write).

Первый аргумент команды — адрес, второй — значение. Как можете видеть, оба аргумента указаны в виде hex-чисел. В данном случае так удобнее. Но можно указывать аргументы и в привычном 10-тичном формате.

mspdebug.2

Как можете видеть, оба аргумента указаны в виде hex-чисел. В данном случае так удобнее. Но можно указывать аргументы и в привычном 10-тичном формате.

Светодиоды не зажглись. Почему?

Да, потому что в самих регистрах вывода записаны нули, а зажигание происходит записью единиц.

Зажжём красный светодиод, который висит на нулевом бите:

mspdebug.3

Теперь зажжём зеленый и одновременно погасим красный:

mspdebug.4

Зажжём оба:

mspdebug.5

Погасим оба:

mspdebug.6

Как видите, всё очень хорошо и легко управляется с компа.

Команда для чтения байта по заданному адресу еще проще:

mspdebug.7

Возможно, вы ожидали, что команда чтения будет называться mr, но это не так! Команда называется md (от memory dump).

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

Здесь мы произвели считывание трёх последовательных адресов, начиная с адреса 0x0020. На этих адресах размещаются регистры P1IN, P1OUT и P1DIR.

По результатам чтения мы видим, что в регистре направления порта содержится значение 0x41 — то самое, которое мы туда поместили — выводы (линии, биты) порта P1, подключённые к светодиодам, работают на выход, а остальные — навход

Мы так же видим, что в регистре вывода P1OUT в настоящий момент записаны нули. Всё правильно — мы же погасили светодиоды.

А вот в регистре P1IN, вопреки нажим ожиданиям, что там должны быть нули, мы видим число 0x08.

На самом деле всё правильно! На линию (бит) 3 подключена кнопка и внешний резистор, который тянет ножку порта к питанию. Поэтому мы видим здесь единицу. Нажатие на кнопки приведет к «придавливанию» линии к нулю.

Попробуйте нажать кнопку (не отпуская!) и выполнить еще раз эту же команду:

mspdebug.8

Только не перепутайте кнопки, на плате — их две! Одна из них «RESET».

Вы видите, что состояние регистра P1IN изменилось? Вот и отлично!

Команада md позволяет не указывать второй аргумент. В этом случае она выводит 64 байта:

mspdebug.9

Поскольку мы уже умеем обращаться с ячейками памяти — писать и читать из них, то было бы логично следующим шагом научиться работать с блоками памяти — сохранять содержимое памяти микроконтроллера в файле на компе и считывать обратно.

Сохранение блока памяти выполняется командой hexout. У этой команды три аргумента: начальный адрес, количество байт и имя файла.

Давайте сохраним в файле msp430f2001.info.hex значение всех четырёх сегментов информационной флешь-памяти. Информационная память расположена с адреса 0x1000. У микроконтроллера MSP430F2001 сегменты информационной памяти имеют размер 64 байта, следовательно, нам нужно сохранить 256 байт. Выполняем команду:

mspdebug.10

Теперь давайте откроем еще одно окно терминала и посмотрим, что у нас получилось:

mspdebug.11

Ага! Появился файл размером 716 байт. А что у файла внутри?

mspdebug.12

Ну, собственно вот так и происходит промышленный шпионаж, примерно так и крадутся коды из незащищённых микроконтроллеров.

Обратный процесс загрузки кода из файлов в память микроконтроллера может осуществляться двумя командами: командой load или командой prog. Команды почти одинаковые, разница ли в том, что команда prog прежде чем загрузить код из файла, стирает память. А команда load «грузит» код из файла поверх старого содержимого. Это бывает полезно, когда нужно объединить старое и ново содержимое, разумеется, находящихся на разных адресах.

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

Ну и раз у я заговорил о программировании флешь-памяти, то нужно обязательно упомянуть команду стирания — erase. Эта универсальная команда позволяет стереть либо всю программную память, либо одновременно и программную, и информационную память, либо стереть один заданный сегмент памяти.

Я не расписываю в подробностях работу этих команд. Я ими редко пользуюсь. Программирование микроконтроллера осуществляется немного другим способом.

Для заливки кода в микроконтроллер нет необходимости запускать mspdebug, а потом в нём вводить команду prog. Всё это делается значительно проще!

Если вы вернетесь в предыдущий урок и повнимательнее посмотрите на файл Makefile, то увидите, что на самом деле программирование микроконтроллера осуществляется командой:

$ mspdebug rf2500 "prog myprog.elf"

Здесь мы запускаем mspdebug  и «скармливаем» ему команду «prog myprog.elf». Дебаггер честно её выполняет и возвращает управление в оболочку.

Под занавес второго действия «Марлезонского балета» я напомню, что выход из командной среды mspdebug можно осуществить командой exit. Но если вы понимаете, как работает терминал, то можете воспользоваться комбинацией Ctrl-D.

Кое-какую помощь по командам и опциям mspdebug вы можете получить через команду help с указанием команды, по которой хотите получить краткую помощь.

Проект mspdebug не стоит на месте, он неспешно развивается. Просматривая распечатанное года три назад руководство по mspdebug я с удовольствием обнаружил, что в новой версии дебаггера (ver. 0.22) имеются команды заполнения памяти заданным значением и добавлены отладочные команды для слежения за изменением переменных в памяти. Так что, когда вы будете читать этот текст, то наверняка в дебаггере появится ещё что-нибудь «вкусненькое».

Я понимаю, что я слегка вас приутомил и всё никак не перейду к описанию процесса отладки программ под дебаггером. Но я прошу вас набраться терпения и поиграться с новой командой заполнения памяти fill. Весьма высока вероятность, что она нам может понадобиться.

Для начала давайте посмотрим на содержимое оперативной памяти. Оперативной памяти в mMSP430F2001 всего 128 байт, и расположена она на адресах от 0x0200 по 0x027f.

Вот, содержимое моей «оперативы»:

mspdebug.13

Там сплошной мусор. У вас будет свой мусор.

Не вдаваясь в подробности, что там за мусор, давайте заполним 16 байт памяти начиная с адреса 0x0220 нулями, а следующие 32 байта значением 0x55. для этого выполним две команды:

mspdebug.14

И еще раз выведем содержимое памяти на терминал:

mspdebug.15

У меня получилось. Надеюсь у вас тоже всё хорошо.

Да, к стати! Вы знаете, что комбинация клавиш Ctrl-L позволяет очистить окно терминала? А клавиши со стрелками (клавиши управления курсором) позволяют прокручивать список команда, которые вы недавно выполняли. И здесь точно также работает клавиша Tab — автоматически дописывает названия файлов и директорий.

В следующем уроке мы создадим простенький проект, напишем программу с ошибкой в логике, откомпилируем, зальем код в микроконтроллер и героически отдебажим прогу — найдем ошибку!

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s