воскресенье, 24 марта 2013 г.

Книга по MinGW


Недавно вышла хорошая книга, посвященная разработке программ на C++ под Windows с помощью свободного инструментария MinGW.

В ней вы найдете исчерпывающую информацию для того, чтобы начать работать с MinGW:
  • инструкции по установке необходимого ПО
  • подробное описание настройки ПО
  • примеры разработки программ на MinGW с использованием популярных Open Source библиотек (Qt, Gtk+, wxWidgets)
  • пример портирования проекта Visual Studio на MinGW
  • интегрирование MinGW с популярными IDE системами

В книге подробно описаны этапы компиляции, отладки и профилирования программ средствами MinGW.
Книга будет интересна всем разработчикам, которые интересуются альтернативными, качественными и бесплатными средствами разработки на C++ под платформу Windows.

Ссылка для заказа книги:
http://www.packtpub.com/mingw-starter/book

суббота, 28 апреля 2012 г.

Git быстрый старт

Настройка gitconfig
Перед началом работы с git необходимо указать имя и email автора локальных коммитов:
git config --global user.name "Name Surname"
git config --global user.email you@yourdomain.example.com

Информация об авторах коммитов отображается в истории репозитория по команде:
git log

Настройки для подсветки вывода команд git:
git config --global color.branch auto
git config --global color.diff auto
git config --global color.interactive auto
git config --global color.status auto

Настройка редактора для правки комментариев коммитов:
git config --global core.editor "mcedit"

Указанные выше команды генерируют файл .gitconfig в домашнем каталоге пользователя. Этот файл можно править вручную, без использования команды git config.

Примерный вид файла .gitconfig
[user]
    email = you@yourdomain.example.com
    name = Name Surname
[receive]
    denyCurrentBranch = ignore
[color]
  branch = auto
diff = auto
interactive = auto
status = auto
[core]
eol = lf
editor = mcedit

Отличия от svn
В отличие от системы контроля версий svn в git локальный и удаленный репозитории могут изменяться независимо. Другими словами операция "коммит" и публикация изменений представляют собой два отдельных действия.

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

В git все игнорируемые файлы и каталоги указываются в файле с именем .gitignore. Этот файл должен лежать в корневом каталоге проекта (там же где и каталог .git).

Основные команды
Создание нового локального репозитория:
git init

Клонирование удаленного репозитория
git clone <адрес репозитория>

Работать с удаленным репозиторием можно через протоколы ssh или http. В случае использования http удаленный репозиторий будет доступен только для чтения.

Создание коммита на основе всех текущих изменений (аналог svn commit):
git commit -a

Все текущие изменения можно добавить в последний коммит:
git commit --amend -a

Добавления нового файла в репозиторий:
git add <имя файла>

Удалить файл из репозитория можно просто удалив файл и сделав коммит всех текущих изменений. Либо специальной коммандой:
git rm <имя файла>

Для публикации локальных коммитов  в удаленный репозиторий:
git push origin master

origin - имя удаленного репозитория (по-умолчания после клонирования репозиторий называется origin)
        master - имя ветки в которую публикуются коммиты (главная ветка называется master, аналог trunk в svn)

Посмотреть удаленные репозитории с которыми взаимодействует локальный репозиторий можно командой:
git remote

Подробная информация об удаленном репозитории:
git remote show origin

Для получения коммитов из удаленного репозитория (аналог svn checkout):
git pull origin master

  master - имя ветки удаленного репозитория из которой получаем коммиты

Для обновлении информации об удаленном репозитории надо выполнить (аналог svn update):
get fetch origin

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

Посмотреть текущие незакоммиченные изменения в локальном репозитории:
git diff

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

Посмотреть отличие локального репозитория от удаленного (включая и коммиты и незакоммиченные изменения):
git diff origin/master

Откатить незакомиченные изменения в файле:
git checkout <имя файла>

Откатить все незакоммиченные изменения:
git checkout -f

Откатить состояние локального репозитория до определнного коммита:
git reset --hard 54f9ebec915f444297fd50812061ea2a4240b0fe

  54f9ebec915f444297fd50812061ea2a4240b0fe - id коммита (выводится в истории командой git log)

Сформировать патчи по коммитам:
git format-patch -n 54f9ebec915f444297fd50812061ea2a4240b0fe

  54f9ebec915f444297fd50812061ea2a4240b0fe - все коммиты до указанного будут в сгенерированных командой файлах

Приложить патч к локальному репозиторию можно коммандой:
git am -3 <имя файла с патчем>

Alias'ы для bash
Привожу используемые мной alias'ы для интерпретатора командной строки:
alias gitam='git am -3'
alias gitan='git annotate'
alias gitb='git branch'
alias gitbr='git branch -r'
alias gitc='git commit'
alias gitca='git commit -a'
alias gitcam='git commit --amend'
alias gitcf='git checkout -f'
alias gitch='git checkout'
alias gitchf='git checkout -f'
alias gitd='git diff'
alias gitdom='git diff origin/master'
alias gitdr='git diff --raw'
alias gitf='git fetch'
alias gitfo='git fetch origin'
alias gitfp='git format-patch "HEAD^"'
alias gitfpn='git format-patch -n '
alias gitl='git log'
alias gitlu='git log -u'
alias gitm='git merge'
alias gitp='git pull'
alias gitpom='git pull origin master'
alias gitpum='git push origin master'
alias gitpus='git push shpigor master'
alias gitr='git remote'
alias gitrh='git reset --hard'
alias gitrhh='git reset --hard "HEAD^"'
alias gitrs='git remote show'
alias gitrso='git remote show origin'
alias gitrv='git revert'
alias gits='git show'
alias gitst='git status'
alias gitstu='git status -uno'

Ссылки
1) Конфигурация git
http://www.arthurkoziel.com/2008/05/02/git-configuration/

2) Подробное руководство по git на русском
http://freesource.info/wiki/RuslanHihin/gitusermanual?v=b7s&

3) Подробное руководство по git
http://schacon.github.com/git/user-manual.html

пятница, 13 апреля 2012 г.

Monit

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

Рассмотрим пример конфигурационного файла:
set daemon  5 
set logfile syslog

set httpd port 2812
    allow localhost

# -------------------- Check services -------------------------------
check display-server with pidfile /var/run/display_server.pid
    start program = "/etc/init.d/display-server start"
    stop  program = "/etc/init.d/display-server stop"

check keyboard-server with pidfile /var/run/keyboard_server.pid
    start program = "/etc/init.d/keyboard-server start"
    stop  program = "/etc/init.d/keyboard=server stop"

# -------------------- Check free space -----------------------------
check device varlog with path /var
    if space usage > 80 % then
        exec "/bin/bash -c '/bin/rm -f /var/log/device-servers/*'"

Настройки демона monit
set daemon - интервал с которым будет вызываться демон monit в секундах

set logfile syslog - имя лог файла, куда monit будет писать свои сообщения (можно указать syslog, а можно полный путь до файла)
  
set httpd port 2812 - поднимает web сервер, который вешается на указанный порт. По этому порту через http можно получать данные о состоянии системы. Команда 'monit status' также использует этот порт для вывода состояния системы.

allow localhost - хосты, которым будет выдаваться состояние системы

Мониторинг сервисов
check display-server with pidfile /var/run/display_server.pid - проверка состояния сервиса по указанному pid файлу. Имя сервиса в monit может не соответствовать имени реального сервиса

start program = "/etc/init.d/display-server start" - команда которая будет выполнена если указанный сервис завершит свою работу

stop program = "/etc/init.d/display-server start" - stop команда нужна для корректного перезапуска сервиса. Без нее monit его не перезапустит

Мониторинг свободного места на диске
check device varlog with path /var - проверка состояния устройства, смонтированного по указанному пути. Это может быть, например, раздел жесткого диска или флэш-диск

if space usage > 80 % then - проверяемое условие. В данном случае если занят объем больше 80% общей емкости

exec "/bin/bash -c '/bin/rm -f /var/log/device-servers/*'" - команда, выполняемая если условие истинно

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

2. Для monit важен сам факт наличия строчки 'stop program' для перезапуска сервиса. Указанную команду при перезапуске он не выполняет.

3. Для просмотра данных о состоянии локальной системы можно воспользоваться командой
monit status

Ссылки
1. Информация по настройке
http://mmonit.com/monit/documentation/monit.html
http://www.thegeekstuff.com/2010/11/monit-install-config

2. Примеры конфигурационных файлов
http://mmonit.com/wiki/Monit/ConfigurationExamples

понедельник, 9 апреля 2012 г.

Net Work


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

1. Просканировать сеть на активные хосты
nmap -sP 192.168.0.1/24

    -sP - ping scan
    24 - маска подсети (последние 32-24 = 8 бит отводятся на подсеть, т.е. сканирование диапазона 192.168.0.0 - 192.168.0.255 )

2. Определить ОС хоста
nmap -O 192.168.0.1

Сканирование подсети и определение ОС можно объединить в одну операцию:
nmap -sS -O 192.168.0.1/24

    -sS - TCP SYN сканирование

3. Сканирование портов хоста
nmap -p 1-80 192.168.0.1

    -p 1-80 - диапазон портов для сканирования

4. Сбор статистики по сетевым интерфейсам локального хоста
iptraf

Кроме того позволяет узнать ip адрес хоста с которым идет наиболее интенсивный обмен данными.

5. Вывод содержимого принятых/отправленных пакетов
tcpdump -X -n -i eth5 dst 192.168.0.1 and port 80

    -X - вывод содержимого пакета
    -n - не преобразовывать DNS имена
    -i eth5 - какой интерфейс использовать
    dst - выводятся отправленые на хост пакеты (для принятых - src)

6. Сохранить трафик, а потом просмотреть его

Сохранить:
tcpdump -ni eth5 -w file.cap dst 192.168.0.1 and port 80

    -w - файл для сохранения данных

Просмотреть:
tcpdump -r file.cap

    -r - файл с сохраненными пакетами

Замечания
 1. Для просмотра содержимого передаваемых пакетов иногда удобнее использовать Wireshark. Он в отличии от tcpdump склеивает передачу разбитую на UDP пакеты и представляет ее в удобном для просмотра виде.

Ссылки
http://nmap.org/book/man-port-scanning-techniques.html - типы сканирования nmap
http://www.cyberciti.biz/tips/top-linux-monitoring-tools.html - 20 полезных утилит для мониторинга Linux
http://www.linuxshare.ru/docs/net/tcpdump.html - руководство по tcpdump

пятница, 6 апреля 2012 г.

Linux и KTLX800/pITX

История
Участвуя в разработке встраиваемой системы, столкнулся с одноплатным компьютером KTLX800/pITX.

Для решения поставленной задачи было решено использовать ОС Linux. Естественно встал вопрос - какой дистрибутив выбрать?

По характеристикам одноплатный компьютер оказался достаточно мощным: процессор AMD Geode LX800 на 500 МГц в комплектации с оперативной памятью 1 Гб. В качестве устройства хранения используется MicroSD карточка. Все это значительно расширило круг возможных претендентов.

Требования
Для обеспечения работы конечного ПО (написанного на C++) и удобства его сборки, репозиторий дистрибутива должен иметь пакеты:
1. Boost
2. CMake
3. openssh-server

Сервер openssh нужен для настройки конечной системы, т.к. наличие монитора не предполагается.

Кроме того должна быть возможность установки не Live версии дистрибутива на сборочный сервер.

Damn Small Linux
Скачал на сайте DSL iso образ с syslinux загрузчиком.
Установил на MicroSD по инструкции (вариант Current ISO + Syslinux):
http://www.damnsmalllinux.org/wiki/index.php/Install_to_USB_From_within_Linux

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

Репозиторий DSL:
http://distro.ibiblio.org/damnsmall/mydsl

В репозитории не оказалось Boost и CMake.

Кроме того установить DSL на MicroSD карточку в варианте hd install не удалось.
Пробовал по этой инструкции:
http://www.damnsmalllinux.org/wiki/index.php/Installing_to_the_Hard_Disk

В результате, я получил Live версию Linux, модифицировать которую весьма трудоемко. От дистрибутива DSL пришлось отказаться.

Knoppix
Скачал iso образ с последней версией.

Установил на MicroSD Live версию с помощью программы flash-knoppix.
На одноплатном компьютере Knoppix с карточки стартанул.

Попробовал установить полноценную версию на MicroSD командой
0wn

Не получилось:
No usable partition found

В результате, как и с DSL, получил Live версию. Правда все необходимые пакеты в Knoppix дистрибутиве есть.

Ubuntu 10.04 LTS Server
Скачал iso образ Ubuntu Server.
Сделал загрузочный flash диск с помощью UNetbootin.

Если в качестве файловой системы на flash диске использовать vfat, необходимо проследить чтобы все пути были корректны. Дело в том, что vfat не поддерживает символьные ссылки. Вместо них создаются пустые файлы.
Для корректной установки системы необходимо скопировать на место таких файлов каталоги на которые они должны указывать (кроме корневой ссылки ubuntu).

В процессе установки с flash диска, подготовленного UNetbootin не обнаружился cdrom:
No common CD-ROM drive was detected

Для решения этой проблемы необходимо:

1. По Alt+F2 переключиться на консоль
2. Смонтировать установочный flash диск в /cdrom:
mount -t vfat /dev/sda1 /cdrom
3. Переключится по Alt+F1
4. Указать device file:
/cdrom

Попробовал произвести установку на MicroSD, загрузившись с flash диска на самом одноплатном компьютере.
Установка закончилась с ошибкой:
base-installer: error: exiting on error base-installer/no_codename

Загрузившись с виртуальной машины удалось выполнить установку на MicroSD.
В качестве загрузчика установился Grub.

На одноплатном компьютере Grub успешно стартанул, но ядро загрузить не смог.
Причем никаких ошибок не выводилось - компьютер уходил в перезагрузку.

Вместо Grub установил Syslinux (вариант Manual Install):
https://wiki.archlinux.org/index.php/Syslinux

Теперь при загрузке ядра получил сообщение:
This kernel requires the following features not present on th CPU:
pae
Unable to boot - please use a kernel appropriate for your CPU

Оказывается в Ubuntu Server по умолчанию идет PAE ядро. Процессор AMD Geode LX800 этот режим работы не поддерживает. Поэтому ядро и не загружалось.

С помощью chroot на уже установленную систему на MicroSD поставил обычное generic ядро. Чтобы Syslinux загрузил это ядро необходимо поправить файл:
/boot/extlinux/extlinux.conf

После этого система успешно стартанула.

Весь дистрибутив Ubuntu Server занял порядка 600 Мб. По скорости работы замечаний не возникло. Необходимые пакеты в репозитории Ubuntu есть. В результате было решено остановится на этом варианте.

Замечания
1. Дистрибутив Damn Small Linux не поддерживается с 2008 года.
Поэтому для новых проектов рациональнее использовать альтернативные легковесные дистрибутивы, например Tiny Core Linux:
http://distro.ibiblio.org/tinycorelinux/welcome.html

2. Почему не использовались такие популярные дистрибутивы как Debian, Arch Linux или Gentoo?
Думаю, они отлично подошли бы для решения поставленной задачи. Но до их рассмотрения дело не дошло - дистрибутив был найден.

Ссылки
http://us.kontron.com/products/boards+and+mezzanines/embedded+sbc/pitx+25+sbc/ktlx800pitx.html - информация по KTLX800/pITX на сайте производителя
http://www.damnsmalllinux.org - дистрибутив Damn Small Linux
http://www.knoppix.com - дистрибутив Knoppix
http://www.wp-schulz.de - кастомизация Live версии Knoppix
http://releases.ubuntu.com/lucid - дистрибутив Ubuntu 10.04 LTS Server
http://unetbootin.sourceforge.net - программа для создания загрузочных flash дисков

понедельник, 2 апреля 2012 г.

Программирование PIC24 под Linux

Среда разработки

Для программирования микроконтроллеров есть несколько Open Source и Freeware IDE, которые готовы запуститься под Linux:
PikDev
Piklab
MPLAB X
Но не все так хорошо, как кажется на первый  взгляд.

PikDev и Piklab требуют для своей работы KDE и Qt3. Кроме того все три среды поставляются без компиляторов. Следовательно необходимо найти линуксовый компилятор языка C для микроконтроллера.

Компилятор
Линуксовые компиляторы для контроллеров есть:
Small Device C Compiler
CCS C Compiler
Первый из них - Open Source проект. Но к сожалению он не поддерживает контроллеры семейства PIC24.

Второй - проприетарный. Версия под Linux есть. Но кроме этого есть виндовая демо версия с ограничением на 45 дней. Как раз ее и можно использовать для небольшого проекта.

Запуск под Linux
Для работы с виндовой версией компилятора CCS C решил использовать MPLAB 8.83. Эта среда бесплатна, легко доступна и работает под Wine. Сам компилятор также успешно запускается под Wine.

Единственная проблема заключается в прошивке контроллера.
Для прошивки используется программатор PICkit 2. Драйверов под Linux для него нет. Следовательно Wine никак не сможет его "увидеть". Получается MPLAB позволяет собирать программы, но не осуществляет прошивку.

Прошивка

Ситуацию спасает Freeware программа pk2cmd. Она позволяет работать с PICkit напрямую средствами libusb. Причем эта программа поставляется в виде бинарников как под Windows, так и под Linux. 

Windows бинарники под Wine работать не захотели.

Скачать эту программу можно либо с официального сайта:

Либо отсюда:

Для работы с Pickit2 необходимо добавить правило для udev:
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", SYSFS{idVendor}=="04d8" , SYSFS{idProduct}=="0033", MODE="0666"
Команды для работы с PICkit следующие.

Получить информацию о подключенном устройстве
pk2cmd -PPIC24HJ256GP206 -I
Прошить устройство HEX файлом
pk2cmd -PPIC24HJ256GP206 -W -K -Q -M -F planar_el.hex
Подать напряжение на выход Vdd (запуск)
pk2cmd -PPIC24HJ256GP206 -R -W
Снять напряжение с выхода Vdd (останов)
pk2cmd -PPIC24HJ256GP206
Ключ -W означает питание от внешнего источника. Если контроллер питается от самого PICkit надо использовать ключ -T.

Замечания

1. На самом деле можно обойтись без IDE MPLAB. Компилятор CCS C может собрать бинарник и сгенерировать HEX файл, который принимает на вход pk2cmd.

В моем случае сборка происходит по команде:
wine "C:\Program Files\PICC\Ccsc.exe" +FD "planar_el.c" +DF +LN +T +A +M +Z +Y=9 +EA

2. Среда разработки MPLAB X поставляется с ассемблером. Поэтому если не ставится задача компиляции C кода, она вполне подойдет для работы.

Ссылки

http://pikdev.free.fr - среда разработки PikDev
http://piklab.sourceforge.net/download.php - среда разработки Piklab
http://sdcc.sourceforge.net - SDCC компилятор для микроконтроллеров
http://gputils.sourceforge.net - ассемблер для микроконтроллеров
https://halfgeek.org/wiki/Pk2cmd - команды для работы с PICkit 2 из под pk2cmd

воскресенье, 1 апреля 2012 г.

Кросс-компиляция с MinGW


Задача
Собрать готовый проект Visual Studio С++ на Linux с использованием компилятора MinGW.


Инструменты

Для сборки проекта в системе должны быть установлены следующие пакеты (названия в дистрибутиве Ubuntu 11.04):

1. wine
2. mingw32
3. mingw32-binutils
Названия пакетов даны для дистрибутива Ubuntu 11.04. В других дистрибутивах эти названия могут отличаться.


Реализация
Для простоты рассмотрим сборку уже готового проекта.
Например воспользуемся этим проектом:
http://www.codeproject.com/KB/directx/basicdd.aspx

Его же можно взять из каталога vs-source репозитория:
http://github.com/ellysh/ddraw-mingw.git


Из всего этого проекта нам понадобятся следующие файлы:
BasicDD.cpp
cSurface.cpp
cSurface.h
resource.h
resource.rc
bmp_bigcar_green.bmp
Из файлов BasicDD.cpp и cSurface.cpp удалим строчку:
#include "stdafx.h"
Создадим Makefile.mingw такого содержания:
MINGW=i586-pc-mingw32
MINGWLIB=/usr/$(MINGW)/sys-root/mingw/lib
CC=$(MINGW)-gcc
LD=$(MINGW)-ld
CXX=$(MINGW)-g++
STRIP=$(MINGW)-strip
WINDRES=$(MINGW)-windres -v
RANLIB=$(MINGW)-ranlib
AR=$(MINGW)-ar
RELFLAGS=-D_FORTIFY_SOURCE=2 -O2
CFLAGS=-Wall -Wno-pointer-sign $(RELFLAGS)
CXXFLAGS=-Wall $(RELFLAGS)
LDADD=-static-libgcc
.SUFFIXES: .rc .res .res.o
%.o: %.c
        $(CC) $(CFLAGS) $(ONLYCFLAGS) -c $< -o $@
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@
.rc.res.o:
        $(WINDRES) $^ $@
Это универсальный makefile для проектов на C и C++, собираемых компилятором 
MinGW.


Кроме этого, сделаем Makefile с конкретными целями сборки: 
include Makefile.mingw
CXXFLAGS+=-Wall -I/usr/include/wine/windowsLDADD+=-lgdi32 -luser32 -lddraw /usr/lib/wine/libuuid.a
OBJECTS=BasicDD.o cSurface.oRES=resource.rc
all: test.exe
test.exe: $(OBJECTS) $(RES).res.o
        $(CXX) $^ -o $@ $(LDADD)
$(RES).res.o: $(RES)
        $(WINDRES) $^ $@
clean:
       rm -f $(OBJECTS) $(RES).res.o test.exe
Если все это у вас соберется после команды
make
считайте что вам повезло.


При сборке с версией 1.3.6 оригинального Wine при линковке возникала следующая ошибка:
i586-pc-mingw32-g++ BasicDD.o cSurface.o resource.rc.res.o -o test.exe -static-libgcc -lgdi32 -luser32 -lddraw
BasicDD.o:BasicDD.cpp:(.text+0xa7): undefined reference to `_IID_IDirectDraw7'collect2: ld returned 1 exit status
make: *** [test.exe] Ошибка 1 
Проблема связана с тем, что в libuuid.a отсутствует идентификатор (UIID) интерфейса IDirectDraw7.


Для решения этой проблемы необходимо собрать свою библиотеку libuuid.a, включающую необходимый UIID.

1. Клонируем репозиторий оригинального wine
$ git clone http://source.winehq.org/git/wine.git
2. В файл dlls/uuid/uuid.c добавляем заголовочный файл с нужным UUID:
#include "ddraw.h"
3. Собираем libuuid


После сборки получим 2 файла: 

libuuid.cross.a
libuuid.a
Нам нужен libuuid.cross.a, т.к. он имеет формат статической библиотеки Windows и линкуется с объектным кодом, сгенерированным MinGW.

Копируем этот файл в каталог собираемого проекта.


Исправляем строчку с LDADD в Makefile:
LDADD+=-lgdi32 -luser32 -lddraw libuuid.cross.a
После этого сборка должна работать.

Замечания

1. В новых версиях Wine каталог dlls/uuid может переехать в другое место.
2. На самом деле картинка bmp_bigcar_green.bmp для сборки не нужна.
Все собирается и работает без нее, т.к. картинка уже содержится в resource.rc. Но если возникнет необходимость изменить выводимое изображение, необходимо отредактировать этот bmp файл и добавить его в resource.rc.

Ссылки

http://freesource.info/wiki/RuslanHihin/gitusermanual – руководство по использованию git
http://git.etersoft.ru/people/shpigor/packages/ddraw-test.git – репозиторий готового проекта
http://www.winehq.org – сайт разработчиков оригинального Wine
http://www.codeproject.com – хороший сайт с примерами кода на разных языках