目次: OpenOCD
今まで散々OpenOCDを使っておきながら今更感がありますが、OpenOCDをソースコードからビルドする方法のメモです。
環境依存の部分を減らすためUbuntu 20.04 LTSのDockerイメージを起点にします。初めに依存ライブラリの開発用パッケージをインストールします。ドキュメントを生成するならdoxygenなども必要ですが、今回は省略しています。
# apt-get install -y git gcc g++ autoconf automake libtool pkg-config make \
libusb-1.0-0-dev libhidapi-dev libgpiod-dev libftdi1-dev
ソースコードを取得したらbootstrapを実行して(最初の1回だけで良いです)、configureを実行します。configureの最後にどんな設定が有効になったか一覧が出ます。親切で良いですね。
$ git clone https://git.code.sf.net/p/openocd/code openocd-code $ cd openocd-code $ ./bootstrap (略) $ ./configure --enable-internal-libjaylink (略) OpenOCD configuration summary -------------------------------------------------- MPSSE mode of FTDI based devices yes (auto) ST-Link Programmer yes (auto) TI ICDI JTAG Programmer yes (auto) Keil ULINK JTAG Programmer yes (auto) Altera USB-Blaster II Compatible yes (auto) Bitbang mode of FT232R based devices yes (auto) Versaloon-Link JTAG Programmer yes (auto) TI XDS110 Debug Probe yes (auto) CMSIS-DAP v2 Compliant Debugger yes (auto) OSBDM (JTAG only) Programmer yes (auto) eStick/opendous JTAG Programmer yes (auto) Olimex ARM-JTAG-EW Programmer yes (auto) Raisonance RLink JTAG Programmer yes (auto) USBProg JTAG Programmer yes (auto) Espressif JTAG Programmer yes (auto) CMSIS-DAP Compliant Debugger yes (auto) Nu-Link Programmer yes (auto) Cypress KitProg Programmer yes (auto) Altera USB-Blaster Compatible yes (auto) ASIX Presto Adapter yes (auto) OpenJTAG Adapter yes (auto) SEGGER J-Link Programmer yes (auto) Bus Pirate yes (auto) Use Capstone disassembly framework no
基本的にOpenOCDのconfigureは依存ライブラリを発見したら、関連する機能を自動的に有効にしてくれますので、特に何も指定する必要がありません。が、今回は --enable-internal-libjaylinkを指定してOpenOCDが内蔵しているlibjaylinkを使用しています。
なぜかというとOpenOCDはlibjaylink 0.2以降を必要としますが、Ubuntu 20.04が提供するlibjaylink(パッケージ名libjaylink-dev)はバージョンが0.1.0と古く、インストールしてもSEGGER J-Link Programmerの機能がyesにならないためです。
ログを見ていると--enable-internal-libjaylinkはdeprecatedで将来的に使えなくなるという警告が出ており、使えなくなると困ってしまうのですが……、とりあえず使える限りは使いましょう。
(略) libjaylink configuration summary: - Package version ................ 0.3.1 - Library version ................ 2:0:2 - Installation prefix ............ /usr/local - Building on .................... x86_64-pc-linux-gnu - Building for ................... x86_64-pc-linux-gnu Enabled transports: - USB ............................ yes - TCP ............................ yes configure: WARNING: Using the internal libjaylink is deprecated and will not be possible in the future. (略)
無事configureが成功したらmakeします。バイナリはsrc/ ディレクトリの下に生成されます。
$ make
$ ./src/openocd --version
Open On-Chip Debugger 0.12.0+dev-00248-g56fd04832 (2023-06-28-00:00)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
うまくいったようです。良かった良かった。
この記事にコメントする
目次: C言語とlibc
組み込みソフトなどでバイナリデータをC言語の配列として記述したいときがあります。毎回手で変換するのは面倒ですし、スクリプトや実行バイナリだと移植が面倒(特にWindows)で、意外と悩ましいです。
もしcmakeだけで実装できれば移植の心配はなくなる(cmakeが対応しているプラットフォームに限る)のでは?と思い、試しに作ってみました。変換の本体は下記の関数です。
function(convert_bin2c input_file output_file c_var_name)
file(READ ${input_file} BIN_HEX HEX)
file(SIZE ${input_file} BIN_LEN)
# Wrap lines per 16bytes
string(REPEAT ".." 16 REGEX_PAT)
string(REGEX REPLACE "(${REGEX_PAT})" "\\1\n" BIN_HEX_WRAP ${BIN_HEX})
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " BIN_ARRAY ${BIN_HEX_WRAP})
# C format
set(C_H_INC "#include <stdint.h>")
set(C_H_LEN "const size_t ${c_var_name}_len = ${BIN_LEN};")
set(C_H_DAT "const uint8_t ${c_var_name}_dat[] = {\n${BIN_ARRAY}\n};")
# Generate header
file(WRITE ${output_file} "${C_H_INC}\n\n${C_H_LEN}\n${C_H_DAT}\n")
endfunction()
処理の概要は下記のとおりです。cmakeは文法にクセがありすぎて見づらいし書きづらいし最悪ですが、やっていることは難しくありません。
なおfile(SIZE) はcmake 3.14、string(REPEAT) はcmake 3.15で追加された機能なので、古すぎるcmakeだと動かないと思います。詳細はcmakeのドキュメントをご確認ください。
例えば下記のように使います。
convert_bin2c(${CMAKE_SOURCE_DIR}/test.bin ${CMAKE_BINARY_DIR}/include/bin.h array_binary)
ソースコードディレクトリ直下のtest.binをビルドディレクトリのinclude/bin.hに変換し、array_binary_dat(配列本体)という名前にします。
これだけだと合っているか間違っているか確認しづらいので、動作確認用に簡単なソースコード一式を作りましょう。
cmake_minimum_required(VERSION 3.16)
project(test_bin2c)
enable_language(C)
add_executable(test_bin2c)
target_sources(test_bin2c PRIVATE main.c)
target_include_directories(test_bin2c PRIVATE
${CMAKE_BINARY_DIR}/include
)
function(convert_bin2c input_file output_file c_var_name)
file(READ ${input_file} BIN_HEX HEX)
file(SIZE ${input_file} BIN_LEN)
# Wrap lines per 16bytes
string(REPEAT ".." 16 REGEX_PAT)
string(REGEX REPLACE "(${REGEX_PAT})" "\\1\n" BIN_HEX_WRAP ${BIN_HEX})
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1, " BIN_ARRAY ${BIN_HEX_WRAP})
# C format
set(C_H_INC "#include <stdint.h>")
set(C_H_LEN "const size_t ${c_var_name}_len = ${BIN_LEN};")
set(C_H_DAT "const uint8_t ${c_var_name}_dat[] = {\n${BIN_ARRAY}\n};")
# Generate header
file(WRITE ${output_file} "${C_H_INC}\n\n${C_H_LEN}\n${C_H_DAT}\n")
endfunction()
convert_bin2c(${CMAKE_SOURCE_DIR}/test.bin ${CMAKE_BINARY_DIR}/include/bin.h array_binary)
実行ファイル名はtest_bin2cでソースコードはmain.cです。変換対象のバイナリはtest.binとしました。変換後のC言語ソースコードはビルドディレクトリの下のinclude/bin.hとしました。
動作確認用のmain.cとtest.binは下記の通りです。
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <bin.h>
static void dump(const uint8_t *dat, size_t len)
{
printf("00000000: ");
for (size_t i = 0; i < len; i++) {
printf("%02x ", dat[i]);
if (i % 16 == 7) {
printf(" ");
}
if (i % 16 == 15) {
printf("\n%08x: ", (int)(i + 1));
}
}
printf("\n");
}
int main(int argc, char *argv[])
{
dump(array_binary_dat, array_binary_len);
return 0;
}
$ cat test.bin aaaa bbbb cccc DDDDD EEEEE FFFFF
あえて説明するほどでもないですが、main.cは配列を16バイトずつダンプするだけのプログラムです。test.binはこのデータのままでも、お好きなデータに置き換えて試しても良いです。
これでビルドできるはずですので、確認します。ビルドツールをNinjaにしたのは私の単なる好みなので、何を使っても良いです。動くはず。
$ cmake -B build -G Ninja ./ -- The C compiler identification is GNU 12.2.0 -- The CXX compiler identification is GNU 12.2.0 -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working C compiler: /usr/lib/ccache/cc - skipped -- Detecting C compile features -- Detecting C compile features - done -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/lib/ccache/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/katsuhiro/share/projects/c/test-cmake-bin2c/build $ ninja -C build ninja: Entering directory `build' [2/2] Linking C executable test_bin2c
生成されたヘッダファイルを確認します。コンパイルは通っているので文法的には間違っていないと思いますが、一応ご紹介ということで。
$ cat build/include/bin.h
#include <stdint.h>
const size_t array_binary_len = 33;
const uint8_t array_binary_dat[] = {
0x61, 0x61, 0x61, 0x61, 0x0a, 0x62, 0x62, 0x62, 0x62, 0x0a, 0x63, 0x63, 0x63, 0x63, 0x0a, 0x44,
0x44, 0x44, 0x44, 0x44, 0x0a, 0x45, 0x45, 0x45, 0x45, 0x45, 0x0a, 0x46, 0x46, 0x46, 0x46, 0x46,
0x0a,
};
変換結果は特に問題なさそうなので、動作確認します。正しく変換できているかどうか、hexdumpの出力と比較します。
$ ./build/test_bin2c 00000000: 61 61 61 61 0a 62 62 62 62 0a 63 63 63 63 0a 44 00000010: 44 44 44 44 0a 45 45 45 45 45 0a 46 46 46 46 46 00000020: 0a $ hexdump -C test.bin 00000000 61 61 61 61 0a 62 62 62 62 0a 63 63 63 63 0a 44 |aaaa.bbbb.cccc.D| 00000010 44 44 44 44 0a 45 45 45 45 45 0a 46 46 46 46 46 |DDDD.EEEEE.FFFFF| 00000020 0a |.| 00000021
動きました。結果も間違ってなさそうです。
思いつく欠点としては、巨大なファイルを扱うとcmakeが遅かったりメモリ食いすぎて死んじゃう気がします。が、cmakeが扱いきれないレベルの巨大配列をソースコードに書くこと自体、設計が間違っていると思うので、処理速度や巨大ファイルの扱いはあまり気にしないことにします。
この記事にコメントする
| < | 2023 | > | ||||
| << | < | 06 | > | >> | ||
| 日 | 月 | 火 | 水 | 木 | 金 | 土 |
| - | - | - | - | 1 | 2 | 3 |
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | - |
25年10月15日
25年10月18日
22年5月5日
25年10月19日
23年4月11日
06年4月22日
25年10月17日
25年10月6日
25年10月13日
20年10月23日
25年10月12日
20年8月29日
19年1月13日
18年10月13日
18年9月3日
18年8月20日
18年7月23日
18年7月22日
18年10月14日
18年11月10日
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
過去日記について
アクセス統計
サーバ一覧
サイトの情報合計:
本日: