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

Я создал и отладил небольшой проект на базе платы MSP-EXP430G2 и установленным на неё микроконтроллером MSP430F2001.

IMG_1005

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

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

Вообще логические ошибки характеризуются тем, что компиляторы их не способны обнаружить. Код компилируется на «ура!», но программа не работает.

Почему не работает? А на этот вопрос мы сейчас и будем искать ответ.

— От винта! (с) фраза из советского кинофильма «В бой идут одни старики»

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

Если у вас всё еще не установлена система контроля версий git, то сейчас самое время её установить. Если git уже установлен, то смело прыгайте к клонированию проекта.

В Debian-е перейдите на уровень root и выполните следующие команды:

# apt-get update
# apt-get upgrade
# apt-get install git

Комадны в Ubuntu :

$ apt-get update
$ apt-get upgrade
$ sudo apt-get install git

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

$ git clone https://github.com/zhevak/mspdebugging.git

У меня в домашнем директории имеются помимо других три специальных рабочих поддиректория: del, test, work.

В директории work я веду ответственные проекты. Здесь растёт и вызревает мой «хлеб». Поддиректории проектов из этого директория я дублирую на других носителях и выкладываю на Гитхаб и Битбакет. Потерять что-нибудь отсюда равносильно утрате члена семьи!

В директории test я произвожу пробные работы. Это экспериментальная площадка для опытов. Обычно отсюда отлаженные технологии плавно перетекают в work. В этом директории тестовые проекты обычно долго живут. Специально я их нигде не сохраняю и особенно не забочусь о их судьбе.

Третий директории del используется как временная площадка для коротких экспериментов. Иногда я его даже чищу. Но в основном судьба его содержимого меня вообще не волнует. Поигрался с проектом и выкинул.

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

mspdebugging.1

Затем я перешел в этот поддиректорий. (Будете повторять те же действия — помните, что слово «mspdebugging» не нужно набирать полностью! Вы ведь знаете назначение клавиши Tab ?)

Надеюсь, у вас всё получается.

Теперь самое время начать работать как «настоящие программисты». Я имею в виду, что прожженые программеры не работают в основной ветке, они сразу создают свою веточку и в ней упражняются. Давайте и мы так же сделаем.

Следующая команда создаст новую ветку и переключит проект на неё.

$ git checkout -b alex

Ну, поскольку моё имя Александр, то и ветку я создам подстать своему имени. Вообще правил наименования много.

mspdebugging.2

Я выполнил еще одну команду:

$ git branch -vv

Эта команда выводит на терминал имена веток проекта и показывает (цветом и символом ‘*’), какая из них является текущей. Ну, в общем, мы видим, что мы находимся на ветке alex.

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

В общем, проект состоит из главного файла, в которм размещается функция main и файла, который отвечает за работу с «голым железом». Первый файл у меня так и называется — main.c, а второй носит тоже довольно-таки типовое имя — hal.c.

Процесс управления зелёным светодиодом сосредоточен в главном файле — main.c, а процесс управления красным светодиодом — в файле hal.c.

Давайте бегло (не вдаваясь в детали) проанализируем структуру проекта. В файле main.c в главной функции main(), как это и положено, прописан бесконечный цикл. В этом цикле четыре команды: две из них зажигают и гасят светодиод, и две — осуществляют задержку времени. Задержка времени выполняется с помощью вызова функции delay_500ms(), которая в цикле вызывает другую функцию delay_10us(). Думаю, что тут у вас не должно возникнуть трудностей.

Управление красным светодиодом будет несколько посложнее. Как я уже говорил, управление красным светодиод осуществляется в прерывании от таймера. Значит, нам нужно запрограммировать таймер.

Однако, я чувствую, что я вас немного утомил. К коду мы ещё вернёмся, а сейчас давайте займёмся более интересным делом. Считайте, что настало время компиляции проекта. Чтобы лишняя информация не отвлекала я нажал Ctrl-L для очистки экрана, после чего ввел команду make:

mspdebugging.3

Компиляция, как я и обещал, прошла без сучка, без задоринки. Размер программы 252 байта. В результате компиляции были созданы несколько файлов, среди который файл mspdebugging.elf и mspdebugging.lst.

mspdebugging.elf — это тот самый файл, ради которого затевался проект. Из него утилита mspdebug «вытянет» код и зальёт его во флешь-память микроконтроллера.

Другая утилита на основе этого же файла определила объем кодов программы и объем данных. Эти цифры мы видим на экране.

С помощью еще одной утилиты из этого же файла получен файл ассемблерного листинга, совмещенный с Си-ными кодами. Этот знакомый нам файл mspdebugging.lst.

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

Команда:

$ caja .

выведет на консоль окно файлового менеджера caja. Эта команда применяется в Debian. В Ubuntu там свой файловый менеджер. К сожалению, я не знаю, какой там нынче файловый менеджер. Мой компик слабенький для Ubunt-ы. Поэтому, давайте как-нибудь сами!

Обратите внимание на точку в конце строки! Точка — это имя текущего директория. (А вот, вы не знали! Да?) Без точки файловый менеджер откроется в домашнем директории, а не там, где мы сейчас находимся.

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

$ pluma *.[ch] Makefile

Линукс — очень приятный инструмент, когда его знаешь! В этой команде используются регулярные выражения, в частности, чтобы не перечислять имена файлов использован шаблон *.[ch]. Шаблон который говорит, что подходят все файлы, которые заканчиваются на букву ‘c’ или ‘h’, причём перед последней буквой должна стоять точка.

В строке указан также Makefile. Он такой один, других, похожих на него, — нет. Нет никакого смысла в шаблоне для одного файла, поэтому тупо вносим его имя в строку. И опять же! Нет смысла набирать всё имя файла. Введите большую букву ‘M’ и нажмите на Tab. Оболочка терминала сама сделает за вас всю оставшуюся работу.

mspdebugging.4

В текстовом редактор откроются сразу несколько вкладок, так как мы загружаем все Си-шные файлы (), все хэдерные

Теперь распределите окна на экране примерно так, как у меня:

mspdebugging.5

Ну, собственно, это есть наша IDE для нищебродов, в ней мы и будем работать.

Итак, программа у нас откомпилирована, нам остается только залить её в микроконтроллер. Выполняем команду:

$ make load

mspdebugging.6

и… чуда не произошло, программа не заработала. Не один светодиод не загорелся.

Ну, что, Охотники за приведениями? Ваш выход. Вперед!

Запускаем отладку:

$ make debug

mspdebugging.7

С чего начинается работа микроконтроллеров MSP430 после подачи питания?

Правильно! — Со считывания из таблицы векторов прерываний вектора сброса (иными словами адреса), который находится на адресе 0xFFFE-0xFFFF.

Таблица векторов небольшая. У младших представителей MSP430 количество векторов всего 16. Давайте выведем целиком всю таблицу — распечатаем содержимое з2-ух байт памяти начиная с адреса 0xFFE0:

mspdebugging.8

Не трудно видеть, что в таблице всего три активных адреса, на которые показывают все вектора — 0xFC00, 0xFC5C и 0xFC8E.

Вектор сброса указывает на начало флешь-памяти — 0xFC00. Отсюда и начинается работа кода. Вектор, который располагается на адресе 0xFFF2 — это вектор обработчика прерывания от таймера. Обработчик находится на адресе 0xFC8E. Остальные прерывания не задействованы, поэтому их вектора направлены на заглушку, которая находится на адресе 0xFC5C.

Итак, мы видим, что в первом приближении таблица более-менее соответствует нашим ожиданиям. Значит, проблема неработоспособности находится не в таблице, а где-то в коде.

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

Так вот, это служебный код — это не наш код. Не мы его писали. И проблемы скорее всего не в нём. Но как бы нам так сделать, чтобы после запуска попасть сразу на начало нашей функции main(), а заниматься прохождением служебного кода. Да и вообще — с какого адреса начинается main()?

Ответы на эти вопросы лежат в файле mspdebugging.lst и ещё в одном месте, о котором я скажу чуть позже. А пока давайте откроем в редакторе файл mspdebugging.lst и пробежимся по его содержимому.

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

Попробуйте найти адрес функции main(), у меня это адрес 0xFC3E. Учтите, что ваш и мой компиляторы могут отличаться, поэтому нет гарантии, что наши машинные коды совпадут.

Прокрутите листинг в самый низ, обратите внимание на таблицу векторов. Как видите, ана находится в полном соответствии с тем, что нам сообщил mspdebug.

Теперь прокрутите листинг вверх, найдите начало кода. Оно находится сразу за таблицей символов. Обратите внимание на то, что адреса начинаются со значения 0xFC00. Это начало флешь-памяти.

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

(mspdebug) dis 0xfc00

mspdebugging.9

Сравните с листингом. Ну что, более-менее получается ориентироваться на местности?

Давайте те же действия произведем для функции main(). У меня это адрес 0xFC3E, у вас он может оказаться несколько другим.

(mspdebug) dis 0xfc3e

mspdebugging.10

Сравните с листингом.

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

Давайте загрузим таблицу символов в отладчик. Для этого выполним команду:

(mspdebug) sym import mspdebugging.elf

И опять же! Нет необходимости набирать длинные имена файлов! Привыкайте к Линуксу — пользуйтесь Линуксовыми приёмами работы. Используйте клавишу Tab!

mspdebugging.11

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

mspdebugging.12

— Ого! Да, это ж совсем другое дело!

Теперь в командах нам можно вместо HEX-адресов функций и переменных указывать их имена. Попробуйте!

(mspdebug) dis main
(mspdebug) dis init_system

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

У нас в программе, в файле main.c имеется одна глобальная переменная — cnt1s. Эта переменная uint16_t занимает в памяти два байта. Мы можем посмотреть значение этой переменной:

(mspdebug) md cnt1s 2

Здесь цифра ‘2’ — это количество байт при распечатке содержимого памяти. Если не указывать это число, то по умолчанию будет распечатано 64 байта.

Однако, давайте попробуем «повыполнять» нашу программу. Чтобы микроконтроллер без нашего участия смог выполнить служебный код и остановиться на входе в функцию main() нужно установить на этот адрес точку останова:

(mspdebug) setbreak main

mspdebugging.13

У нас есть (к сожалению!) всего два слота для аппаратных точек останова. Точка останова для адреса main() находится в нулевом слоте.

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

(mspdebug) reset
(mspdebug) run

mspdebugging.14

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

Итак, мы находимся в начале функции main(), стоим на первой её команде. Эта команда — вызов функции init_system. Я предлагаю, пока не заходить в эту функцию, а сразу перейти к команде

 BIS.B   #0x0040, &0x0021

Для этого я еще раз введу команду для задания точки останова. На этот раз точкой останова будет адрес команды BIS, то есть адрес 0xFC42

(mspdebug) setbreak 0xfc42

Дебаггер сообщает нам, что он разместил точку останова в следующем свободном сокете — в сокете с номером 1.

Теперь еще раз даем команду run, дебаггер позволит выполнить микроконтроллеру какой-то кусок кода и остановит его на точке останова.

Давайте попытаемся оценить ситуацию. Микроконтроллер собирается выполнить команду

 BIS.B   #0x0040, &0x0021

Действие команды состоит в том, чтобы установить по заданному адресу биты, которые указаны к константе. В данном случае константой является число 0x0040, а адресом число 0x0021.

По адресу 0x0021 находится регистр P1OUT. Здесь всё в порядке.

Что касается константы, то она преобразуется в байтовое значение (путём откидывания старшего байта) равное 0x40. Это значение тоже соответствует истине.

Значит, после выполнения этой команды должен загореться зелёный светодиод.

Делаем один шаг по программе:

(mspdebug) step

Светодиод не загорелся. Почему?

mspdebugging.15

Хорошо! Давайте посмотрим, что вообще записано в этом регистре:

(mspdebug) md 0x0021 1

mspdebugging.16

Как мы видим, там все биты, кроме одного находятся в единичном состоянии. Hex-значение FE соответствует битовому значению 11111110. В нулевом состоянии пребывает только нулевой бит. Нулевой бит отвечает за состояние красного светодиода. Но бит зелёного светодиода находится в единице, следовательно зелёный светодиод должен гореть! Но он не горит.

Хорошо! Расширяем поле обзора. Выведем состояние всех трех регистров порта: P1IN, P1OUT и P1DIR, благо они все расположены по трём последовательным адресам — 0x0020, 0x0021, 0x0022.

(mspdebug) md 0x0020 3

Регистр ввода P1IN нас не очень интересует, но посмотреть на его состояние иногда бывает полезно. Ведь состояние этого регистра — это ничто иное как состояние выводов (ножек).

mspdebugging.17

Мы видим, что на всех ножках порта, кроме одной, присутствуют нулевой потенциал. Hex-значение 08 соответствует двоичному значению 00001000. И только на ножке, отвечающей за третий бит, висит логическая единица. Третий бит отвечает за кнопку, и в нормальном состоянии должен быть подтянут к питанию. Так что претензий к кнопке нет.

А вот к чему есть претензии — так это к четвёртому биту, на котором висит светодиод. Вот смотрите, в регистре вывода порта мы чётко видим единицу, но реально напряжение на ноге нулевое.

Такое может быть трех случаях:

  1. Порт физически неисправен,
  2. Порт неправильно сконфигурирован,
  3. Ножка порта физически замкнута на землю (короткое замыкание).

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

Смотрим на значение P1DIR, оно равно 0x01. Иначе говоря только один разряд порта развернут на выход, все остальные являются входами. Естественно, мы не сможем никак зажечь светодиод, поскольку вывод работает как вход, а не как выход.

Скорее всего косяк где-то в коде инициализации портов, который мы как раз и пропустили.

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

Прописываем в регистр P1DIR правильное значение 0x41 (двоичное 01000001):

(mspdebug) mw 0x0022 0x41

mspdebugging.18

Светодиод сразу загорелся. Ага! Отлично.

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

А поскольку у нас в программе стоит точка останова на первой команде в бесконечном цикле, то светодиод должен один раз моргнуть, после чего программ вновь остановится. Другими словами, для каждой итерации цикла мы должны выполнять команду run.

Давайте попробуем!

(mspdebug) run

Однако, с программой всё еще что-то не так. После ввода команды, светодиод погорел какое-то время и погас. Повторный ввод команды run не приводит к зажиганию.

Еще раз выводим содержимое регистров порта

(mspdebug) md 0x0020 3

и видим, что регистр P1DIR опять принял свое неправильное состояние. Почему?

Хорошо! Давайте понаблюдаем. Давайте соберём статистику.

Снова исправляем значение P1DIR на правильное и снова запускаем программу на исполнение.

mspdebugging.19

А вообще, кто-нибудь заметил, что программа остановилась на входе в функцию main(), а не на первой команде в бесконечном цикле?

Вопрос — как так могло случиться?

Теперь понятно, почему светодиод вспыхивал только один раз — ведь программа при перезагрузке каждый раз заново производила инициализацию системы — init_system(), и поэтому регистр P1DIR заново приобретал неправильное значение.

Но всё-таки, почему происходит перезагруpка микроконтроллера?

У нас есть такой замечательный регистр, как регист флагов прерываний IFG1. Он расположен по адресу 0x0002.

Давайте считаем его состояние:

(mspdebug) md 0x0002 1

mspdebugging.20

Значение 07 (00000111) говорит о том, что подняты следующие флаги:

PORIFG — устанавливается когда происходит подача питания на микроконтроллер и он начинает работать. Ну тут понятно — этот флаг будет установлен всегда.

OFIFG — устанавливается при обнаружении неисправности в высокочастотном генераторе. Я не использую высокочастотный генератор. Поэтому тут тоже без вопросов.

WDTIFG — устанавливается когда срабатывает сторожевой таймер.

А вот сторожевой таймер — это и есть та причина, по которой происходит перезагрузка микроконтроллера. Дело в том, что в других микроконтроллерах (AVR, STM32) сторожевой таймер после включения или сброса микроконтроллера находится в выключенном состоянии, и чтобы начать с ним работать, его нужно включить.

В микроконтроллерах MSP430 много чего сделано с точностью до наоборот по сравнению с другими участниками рынка. У меня такое чувство, что Texas Instrumrnts по какой-то причине делает это специально. Если весь мир делает так, то инженеры TI обязательно сделают наоборот.

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

Программы на Си конструируются компиляторам и линковщиками таким образом , что сначала после сброса работает стартовый код, к которому у пользователя нет доступа. А потом, когда этот код произведет инициализацию стека, произведет инициализацию переменных пользователя — в том числе обнулит массивы, он передаёт управление функции main().

Прекрасное, прекрасное решение! Вопросов нет! Всё логично и очень замечательно!… Замечательно, пока вы не используете MSP430.

Вот смотрите, что происходит на практике. После того, как отработает стартовый код и управление попадет в main(), что обычно делается? Программист прописывает в коде инициализацию различных периферийных устройств, настраивает железо и программные переменные. В больших системах, среди прочей суеты, обычно в конце всех этих процедур еще включается и настраивается сторожевой таймер. И система красиво так взлетает. Красота!

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

Запускаете mspdebug, ставите точку останова на main() и … и убеждаетесь, что сюда управление не попадает. Почему?

Процессор вроде бы работает, заливка кода и проверка после заливки показывают всё ОК. Но железо не работает. Вы бьетесь над проблемой пару дней и приходите к выводу, что неисправна микросхема. Матерясь в полголоса вы срезаете дохлую, на ее место впаиваете новую и … и опять тот же результат — система не работает. Меняете еще раз микросхему, и опять тот же результат. Не может же быть, чтобы вся партия была бракованной

На третьей микросхеме вы начинаете ненавидеть весь мир. Вы производите тестирование микросхемы сторонними мелкими проектами типа светодиодоморгания, и убеждаетесь, что всё очень четко работает. Микросхема чудесная, микросхема исправная. И только по какой-то личной неприязни к вам (не-е, ну почему же еще!?) MSP430 напрочь отказывается работать только с вашей коммерческой программой.

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

Через пару часов прохождения по чужому стартовому коду вы замечаете, что срабатывает сторожевой таймер и код не заверши своей работы, соответственно, так и не передав управление в main(), внезапно прерывается злым собакеном. Вот, сволочь! Печально то, что это не выдуманная проблема, а взятая из жизни! Из конкретной ситуации, которая к счастью, приключилась не со мной.

Проблема в том, что массив вашей программы настолько большой, что на его инициализацию (обнуление) — а это, на минуточку! это оговорено стандартом языка Си — уходит столько времени, что собака успевает вылезти из своей будки и клац-клац за яйца вашу программу.

Проблема в том, что MSP430 — это не AVR и не STM32, у которых собака изначально заколочена в будке и вы ее сами выпускаете тогда, когда вам это надо. Здесь собака бегает по городу сразу, и хватает за жопы все зазевавшиеся программ без разбору.

Проблема в том, что msp430-gcc — это несколько вещь в себе, У вас нет такой же легкой возможности, как у STM32 написать свой стартовый код, сконфигурировать по своему усмотрению линковщик. Все, что доступно вам — начинается от входа в main(). Но когда система падает даже не доходя до main() это говорит о особом даре разработчика, сконструировавшего MSP430.

Конечно, при определённом упорстве и настойчивости, всё эти трудности преодолимы. Но иногда всё это смахивает на мазохизм.

Сама по себе машинка MSP430, конечно, хорошая! Тут даже нечего и говорить! Но иногда находишь в ней такие косяки, что задумываешься — ребята, а может, послать вас куда подальше с вашим перевёрнутым вверх ногами видением мира? А потом, пойдёшь на кухню, выпьешь успокоительную чашечку цикория, и приходишь к понимаю, что хрен ты слезешь с этой иглы, программист хренов! Потому заказчик платит не за то, на чём лучше, легче, приятнее, «предсказуемее» и правильнее писать, а за то, чтобы ты выпиливал неработающий код, писал новые «костыли» и делал новые «подпорки». Менять камень в фундаменте всегда дорого. Ведь всем известно, что чем на более раннем этапе разработки была допущена ошибка, тем дороже обходится ее исправление. Костыльно-подпорочные технологии — это быстрое и дешевое решение, поэтому они имеют большое преимущество даже над правильными технологиями. И в конце концов разработчик даже находит утешение для себя — типа «к тому моменту, когда конструкция 15-этажного сарая начнет обваливаться из-за кривизны фундамента, меня уже в этом проекте не будет». И он тоже по своему прав! Вот и получается, что в результате движения по траектории наименьшего сопротивления и погони за экономией бюджета, достигаются немного не те цели, ради которых затевалась движуха.

Тот, кто писал проекты для STM32 и отлаживал программы в нормальном дебаггере под OpenOCD, тот понимает, насколько тесны стены MSP430. А тот, кто писал код только под MSP430 и отлаживал его, тот никогда не сможет понять на сколько красив и совершенен может быть мир Cortex. если человек никогда не катался на велике, как ему объяснить, что такое свобода перемещения? Если человек никогда не плавал, как ему объяснить, что такое свобода тела и любовь прозрачной солёной волны в открытом море?

Не-е. Надо с MSP430 как-то завязывать. Слазить надо с этой архитектуры. Тем более, есть более вкусные, и по деньгам, к стати, в разы дешевле.

Эх!..

Ладно, задавайте ваши вопросы, буду отвечать.

 

9 responses to “Практика использования mspdebug. Светодиодоморгалка

  1. Я не могу окончательно слезть с pic и avr потому что eeprom в stm32 увы, например а объём кода всегда в разы больше чем требовался мне ранее. Ну и на asm я изъясняюсь как на родном языке а на си не то что бы.

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

      Вот например, у меня каротажных делах… Для передачи данных по многокилометровому кабелю я использую тип модуляции Манчестер-2. Совокупность решений для формирования и приёма таким способом очень легко осуществляется ТОЛЬКО (я подчёркиваю) на базе AVR. Другие микроконтроллеры тоже позволяют сформировать Манчестер-2, но там не получается это сделать так же красиво с точки зрения инженерного решения. Получается какое-то грязное исполнение, много костылей и палок.

      Ну, казалось бы — чего сложнее сформировать модулированный код Манчестер-2 из потока данных и синхросигнала на классическом вентиле Исключающее-ИЛИ. Классическое решение! В школе это старшеклассники проходят.

      Однако, когда начинаешь реализовывать на практике, то оказывается, что ни MSP430, ни STM32 не позволяют это легко сделать.

      В случае с AVR, я включаю вывод XCK, на который выводится синхросигнал. На выходе TXD пока находится единица и информация не выводится. Но в кабель уже бежит нормальный Манчестер-2. Переходные процессы успокаиваются, линия кабеля приходит в баланс. На приёмном конце после дешифрации Манчестера-2, мы получаем на линии RXD неизменную логическую единицу.

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

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

      В случае с STM32 сразу попадаем на проблемы. USART в STM32 хоть и имеет вывод для выдачи синхросигнала, но (собака!) вырабатывает синхроимпульсы только для информационных битов. Старт- и стоп биты выводятся на вывод RXD без сопровождающих синхроимпульсов. То есть получается, что полноценно сформировать Манчестер-2 можно только для информационных битов, но не для старт- и стоп-битов.

      Это что за Манчестер такой получиться? Как его передавать? А как его потом дешифровать?

      Причем, такое решение в STM32 сделано сознательно. В целях совместимости модуля USART c форматом сигналов интерфейса SPI. Как известно, у SPI нет ни стартовых, ни стоповых битов. Но все информационные биты сопровождаются синхроимпульсами. Таким образом USART может спокойно работать в режиме SPI. Стартовые и стоповые биты, при отсутствии синхроимпульсов, на приёмном конце будут просто проигнорированы. Единственная издержка состоит в том, что поскольку на TXD присутствуют старт- и стоп-битв, того времени на передачу байта потребуется на 20% больше, чем при чистом SPI.

      Хорошо! Допустим по кабелю мы будем передвать не стандартный последовательный код UART, а тот же SPI. Но, разумеется, модулированный по типу Манчестер-2.

      Будет работать? — Нет!

      Почему? — Да просто потому, что даже если нам удастся на приемном конце дешифровать сигнал, то чтобы выделить из него синхросигнал (по сути меандр) — это дополнительные затраты. Ведь, как известно, для стандартного последовательного сигнала UART не нужна синхронизация. Сигнал сам себя синхронизирует в начале каждого байта. Причем, по значению стартового и стоповых битов можно легко судить о том, инвертирован или нет сигнал. В случае приёма и дешифрации SPI из Манчестера-2 возникают большие проблемы.

      Ну, хорошо! Давайте тогда откажемся от модуляции Манчестер-2…

      Классно! А что вы можете предложить в замен? — Проблема в том, что практически предложить-то нечего!

      И вот тут наступает прозрение. Ребята, а ведь в погоне за STM32 мы сломали красивую, более того — РАБОТАЮЩУЮ, конструкцию, а взамен ничего не создали. Что мы делаем? Ради чего?

      Я не упомянул о переходе с AVR на MSP430. Тут примерно те же , если не большие проблемы!

      В общем, единственным красивым решением этой задачи является решение на безе AVR. Другие микроконтроллеры в решении этой задачи будут выглядеть весьма коряво и грязно.

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

      Можно даже формировать Манчкестер-2 чисто программным путём. Не, а почему бы нет! И я уверен, что это тоже заработает. Но когда смотришь на решение на базе AVR, то понимаешь, что альтернативы ему нет. Все остальное — костыли и подпорки.

      Ну дак что — удастся нам слезть с AVR?

  2. Linux пока мало пригоден для встраиваимых систем. К сожалению бедный софт.
    Если хотите «погони за экономией бюджета» и задачи приходится решать несложные то переходите на STM8.🙂

    • Ну, мне уже поздно пить Борджоми.

      В то время, когда на рынке появились STM8, для этих машинок не было под Линукс ни компилятора, ни ассемблера. Прошло еще несколько терпеливых лет в ожидании чуда. Ничего не появилось.

      Возвращаться на Виндовс ради только STM8 не было ни какого желания. Использовать «резиновую женщину» — wine, — тоже не вариант. В общем сила сопротивления STM8 была выше моего желания захомутать её. И в самом деле — нахрена она мне эта натукатуренная красотка? С ней уже сейчас проблемы, я что будет потом?

      В общем, крепость не сдавалась, а брать её в одиночку как-то не пёрло. Особого смысла не было. Я даже опустился до того, сдуру (не иначе!) как-то уговорил Мишу Кона (Michael Kohn) написать релиз ассемблера под STM8. Но сам как-то закрутился и вообще потерял интерес к STM8.

      Сейчас вроде бы что-то уже есть в Линуксе для STM8. Но время упущено, для мелких проектов я использую AVR и MSP430. Для более тяжёлых — STM32. То есть я не страдаю, от того, что в моём арсенале нет STM8.

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

      И если попытаться снизить стоимость изделия путём замены типа микроконтроллера (допустим с AVR на STM32), то на конечной стоимости уменьшения может и не произойти. Даже двух-трех кратный выигрыш в цене микроконтроллеров может легко поглотиться повышенными затратами на затянувшееся время разработки, и необходимость закупки программаторов. То есть не всё так однозначно. Нужно индивидуально разбираться в каждом конкретном случае.

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

      Ну и скажу пару слов про «Linux пока мало пригоден для встраиваимых систем. К сожалению бедный софт».

      Я не очень силён во встраиваемых системах, но мне кажется, что по большей части встраиваемые системы как раз используют Линукс (QNX, ucLinux, Android), а не Windows CE. Хотя опять же, о какой категории встраиваемых систем идет речь! Если только о банковских и платёжных автоматах, то там 50 на 50. А если о каких-нибудь роутерах, смартфонах, кофемолках-утюгах, то в основном используется Линукс. Но не Виндовс.

      А что касается «бедности софта», так это всё индивидуально! Допустим, мне лично — хватает. Меня более чем устраивает.

      Просто я не люблю Виндовс. Да. Я не люблю Виндовс, не смотря на её «богатство софта». Я длительное время работал и в Линуксе, и в Виндовсе. И не понаслышке знаю их положительные и отрицательные моменты. Свой выбор я уже сделал, причём — заметьте, — находясь в сознании и имея практический опыт работы и там, и там. Это на Винду я подсел находясь в бессознательном «детстве», когда не было возможности сравнивать и выбирать операционные системы для работы, и приходилось принимать за эталон то единственное, что вообще у нас было.

      А сейчас выбор — очень большой! Выбирай то, что тебе больше нравиться. Никто тебя не принуждает и не ограничивает. Я не коллекционирую пассатижи, я не коллекционирую софт. И если мне для работы хватает имеющихся программ, то вопроса «бедности софта»у меня нет. Утверждение о недостатке софта в Линуксе уже давно относится к категории надуманных проблем. Нет его — недостатка. Но есть недостаток свободного времени, чтобы всё это разнообразие освоить и применять во благо.

      А за каммент — спасибо!

      • Для STM8 Миша Кон сделал компилятор. Да и компилятор SDCC под них переделали — http://bovs.org/post/111/kompilyator-sdcc-dlya-stm8-v-linux
        А вот с отладкой пока похоже не все так просто — http://sharaga.org/index.php?showtopic=24408😦
        Но если для ваших задач хватает AVR то смысла переходить скорее всего нет. У самого такая ситуация.
        На стоимость конечного изделия влияет стоимость самой микросхемы микроконтроллера тогда когда например нужно сделать 10000 изделий. Даже экономия 0,5 цента на одной микросхеме уже значительная. В то время как для штучных изделий даже удорожание на несколько долларов погоды не делают.

        Под «встраиваемыми система» имелось ввиду те где используют однокристальные ЭВМ (микроконтроллеры). Те о которых вы подумали используют как микроконтроллеры например ARM так и микропроцессоры семейства x86 и ПЛИС.

        А «бедности софта» это то что инструмента для отладки нормального для AVR и MSP430 (хотя бы где-то на уровне VMLab) под Linux я P1OUT |= BIT4; пока не находил.😦
        Да привык я уже к AVR Studio и к IAR’у. Есть еще много другого софта который есть только под Windows. А тот софт что есть для Linux требует «танцев с бубном». Поэтому пока еще не решился перейти на Linux.

        За статью огромное СПАСИБО.

      • 1. Миша сделал не компилятор, а ассемблер. Ассемблер намного легче написать, чем компилятор. Ассемблер реально поднять в одиночку, что собственно, Михаил и продемонстрировал. А вот с компилятором… Вроде Павел Гайдук начинал в одиночку писать Си-компайлер, но потом, вроде бы людей нанял… Врать не буду, не разговаривал с ним на эту тему. Да и давно это было. Уж лет 10 наверно прошло, если не больше. С компиляторами, там — да, сложно. Особенно с оптимизацией кода. Одному точно не вытянуть.

        2. Фраза «Даже экономия 0,5 цента на одной микросхеме уже значительная» — это типичное заблуждение. Ну вот, сами посчитайте! Какая это будет экономия. Пусть будет не пол-цента, а пол-доллара.

        10000 * 0.5 = 5000

        — Пять тысяч долларов, Карл! Пять тысяч!

        Вроде огромные деньги. Вопрос — для кого? Для трудящегося на предприятии — да, это огромная сумма. Но кто ж ему, милому, эту экономию выплатит! Да и с какой стати!

        Я что-то не очень знаю такие предприятия, где это практикуют. Владелец предприятия обычно недоволен разработчиками — долго разрабатывают, просят высокую з/п, занимаются не тем (работать надо, а они новые технологии осваивают), ну и т.д. Но что бы сэкономленную сумму отдали разработчику

        — Нет, сынок! Это — фантастика!

        А теперь посмотрим на экономию с точки зрения владельца предприятия. Предприятие продает какую-нибудь хрень, в которой используется этот микроконтроллер, ну, допустим за 100 долларов.

        Партия изделий величиной 10000 штук принесёт доход размером в

        10000 * 100 = 1 000 000 долларов.

        Вы соизмеряете масштабы? Предприятие у которого оборот в ОДИН МИЛЛИОН ДОЛЛАРОВ будет заморачиваться на какие-то 5000 долларов?

        Конечно, это приятно, когда какой-нибудь Вася-разработчик сэкономил денег владельцу бизнеса. Но это такая мелкая сумма, что ну её нахрен!

        На предприятии, которое выпускает партии электронных изделий по 10000 штук, должно работать от 25 до 50 человек.

        Если мы говорим о России, давайте примем усреднённую зарплату на одного трудящегося равной 1000 долларов в месяц.

        Тогда получается, что согласно сэкономленным средствам на предприятие можно дополнительно принять ещё двух-трёх человек. Не пятерых! Не забывайте про налоги и отчисления!

        И что эти два-три человека на фоне списочного штата 25-50 человек — это серьёзное увеличение темпов развития? Да, не смешите! Тогда две-три беременных тётки приведут к краху это предприятие.

        Так что вся значимость этой экономии на микроконтроллерах — это одни разговоры для курилок.

        3. Я не знаком с VMLab. Может он и делает что-то, но я не думаю, что это какое-то сверх-оружие борьбы с багами. Для отладки моих девайсов мне хватает gnu-тых дебаггеров, светодиодов, осциллографа и последовательного порта для подключения компа в качестве терминала. Разве это этого мало, разве нужно что-то еще? О чём, Вы, уважаемый!

        4.
        <>
        Я не вижу в этом ничего плохого. Давайте посмотрим на детей. Один ребёнок избалован родителями, и каждый раз, когда ему предстоит сделать то-то трудненькое, капризничает, устраивает истерики. Другой ребенок с детства приучен к трудностям. Трудности его не пугают и не угнетают. Наоборот, трудности ребёнка только разогревают. Ребёнок вырастает. Мужчина 40 лет — внутри тот же ребёнок. Стоимость игрушет только другая. Но внутри тот же ребенок с тем же набором эмоций и реакций. Понаблюдайте за людьми, как они реагируют на трудности! Очень, к стати просветляет мозги.

        5. Я не агитирую за Линукс. Отагитировался уже. Понял, что человека не надо никуда тащить. Человек сам должен созреть. Ну если не созрел, то как говорит сволочь Капранов — «Очень жаль!»

      • 1. С компилятор для STM8 сделали из Small Device C Compiler. Кто незнаю не интересовался.

        2. Если «какая-нибудь хрень» стоит 100 долларов то прибыль она принесет гораздо меньшую.
        В реальности все намного хуже. В 2000 мы продавали изделия по 30 долларов, а к 2007 под натиском монополистов (энергокомпаний) и в конкурентной войне с другими предприятиями цена упала где-то до 12-15 долларов. И это в условиях роста цен на материалы, комплектовку, рост зарплат и прочих расходов. Первой пошла под «урезание» сверхприбыль хазяина.🙂 Но небольшую прибыл он некоторое время еще плучал.
        Правда в то время на микроконтроллерах не особо и сэкономишь. АВР были тогда самые дешевые. Основной путь был в «урезании» печатной платы и «оптимизации» комплектовки.🙂

        3. Бывают слачаи что изделия под рукой нет тыкать осциллографом некуда но программу нужно «немного доработать». Та что иногда удобно иметь под рукой эмулятор. Но это так небольшая хотелка.

        4. В данном случае инструмент должен быть удобен и не создавать «трудности», их и без этого хватает.

      • 1. Без комментариев.

        2. Мир очень огромный. Чего только в нём не бывает!

        3. Мир очень огромный. В связи с его огромностью, мире имеют место очень редкие явления, вероятность который стремиться к нулю.

        Ну, например, недавно (в начале Февраля) в Индии погиб водитель автобуса от «прицельного» попадания в него меторита.

        Вопрос: какова вероятность тако стечения обстоятельств? — Ответ: чрезвычайно мала, но не равна нулю.

        Вопрос: следует ли предпринимать какие-либо действия чтобы защититься от таких метеоритов. — Ответ: нет. Слишком мала вероятность и слишком дорого обойдётся защита.

        4. Абсолютно с Вами согласен! Именно по этой причине я пересел на Линукс и обратно не собираюсь! По началу было трудно, и очень хотелось вернуться. Но я выдержал «экзамен». Теперь Линукс, работает на меня.🙂

        И, да! Мне очень приятно, что Вы поблагодарили меня за мой труд. Приятно осознавать, что моя жизнь не только биологическая (жрать, срать, размножаться), а еще я что-то делаю полезное для всех нас.

  3. Касательно Atmega вот сегодня решал что к завтра смастерить: паять на макетке мегу8, к которой я легко за пару часов напишу асм-код, или воспользоваться собственной универсальной отладкой на которой уже впаян stm32f100c8t6 но для которой придется весь день создавать программное решение. Победа в перспективе этого проекта досталась stm8 а для тестов пока stm32.

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

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

Логотип WordPress.com

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

Фотография Twitter

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

Фотография Facebook

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

Google+ photo

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

Connecting to %s