« 2011年7月 | トップページ | 2012年5月 »

2011年10月の記事

LPCXpresso IDEでのC++コードサイズ肥大化の対策

前回ポストしたLPCXpresso用のXBee APIモードライブラリですが、コードサイズが100KB程度にまで肥大化することが分かりました。組み込み用としてはでかすぎます。mbedで前回のサンプルと同様のコードをコンパイルするとバイナリサイズは31KBに収まります。

コードサイズが大きくなるトリガーは何となくわかりました。どうも、親にvirtual関数を持つクラスのインスタンスを生成すると、本来必要ないと思われるライブラリの関数がごっそりとリンクされるのが原因と思われます。以下の通り、実験をしてみました。

2011/10/16追記:
audinさんコメントをいただき、viurual関数を持つクラスを使った際のコードサイズ肥大の問題が解決し、サイズを21KBにまで圧縮できるようになりました。


最小構成でコンパイル

まず、以下のように14行目でXBeeクラスのインスタンスだけを生成するサンプルをコンパイルします。

#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif

#include "Xbee.h"

uint8_t atISCmd[] = {'I', 'S'};      // Forces a read of all enabled digital and analog input lines
uint8_t atD1Cmd[] = {'D', '1'};		 // DIO1 control
uint8_t atDBCmd[] = {'D', 'B'};      // Received Signal Strength
uint8_t cmdVal0[] = {0};             // Clear RSSI register
uint8_t cmdVal4[] = {4};			 // Digital output, low
uint8_t cmdVal5[] = {5};			 // Digital output, High

XBee xbee(2);

XBeeAddress64 remoteAddress(0x0013A200, 0x406B7111);    // Specify your XBee address

/*-- Create instance of Command and Response object --*/
// Remote ATIS command to read ADC value (ADC3 is enabled by X-CTU tool)
//RemoteAtCommandRequest remoteSampleRequest(remoteAddress, atISCmd);


int main(void) {

	while(1) {
	}

	return 0 ;
}

Debugビルドですが、この段階でコードサイズが80KB程度になってしまいます。ここで、リンカスクリプトをいじってやるとコードサイズを削減できることを発見。LPCXpresso IDEのリンカスクリプトは通常自動生成ですが、プロパティ設定から;
MCU C++ Linker → Target → Manage Linker Scriptのチェックを外してやると、独自のスクリプトを書くことができます。自動生成される3本のスクリプトをマージし、以下のライブラリ定義部分を書き換えます。

オリジナル:
GROUP(libgcc.a libc.a libstdc++.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)

書き換え:
GROUP(libgcc.a libc.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)

要は、libstdc++.aを削除します。

再度ビルドすると、コードサイズが12,552byteにまで縮小します。mapファイルを見ると、以下の関数がリンクされていることが分かります。

.debug_frame    0x00000000     0x2884
 .debug_frame   0x00000000       0xc8 ./src/Serial.o
 .debug_frame   0x000000c8       0xac ./src/Timer.o
 .debug_frame   0x00000174     0x1714 ./src/XBee.o
 .debug_frame   0x00001888       0x6c ./src/cr_cpp_config.o
 .debug_frame   0x000018f4      0x158 ./src/cr_startup_lpc176x.o
 .debug_frame   0x00001a4c       0x64 ./src/main.o
 .debug_frame   0x00001ab0       0x4c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_pinsel.o)
 .debug_frame   0x00001afc      0x16c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_timer.o)
 .debug_frame   0x00001c68      0x2f8 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_uart.o)
 .debug_frame   0x00001f60       0x38 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(system_LPC17xx.o)
 .debug_frame   0x00001f98       0xa0 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_clkpwr.o)
 .debug_frame   0x00002038       0x20 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_libcfg_default.o)
 .debug_frame   0x00002058       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(bpabi.o)
 .debug_frame   0x000020a8      0x288 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(unwind-arm.o)
 .debug_frame   0x00002330       0xf4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(pr-support.o)
 .debug_frame   0x00002424       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_divdi3.o)
 .debug_frame   0x00002460       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivdi3.o)
 .debug_frame   0x0000249c       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivsi3.o)
 .debug_frame   0x000024bc       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-abort.o)
 .debug_frame   0x000024e4       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-init.o)
 .debug_frame   0x00002510       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-malloc.o)
 .debug_frame   0x00002540       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mallocr.o)
 .debug_frame   0x0000257c       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcpy.o)
 .debug_frame   0x000025ac       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mlock.o)
 .debug_frame   0x000025dc       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sbrkr.o)
 .debug_frame   0x00002608       0xc0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signal.o)
 .debug_frame   0x000026c8       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signalr.o)
 .debug_frame   0x00002704       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-freer.o)
 .debug_frame   0x00002754       0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reent.o)
 .debug_frame   0x000027b8       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_sbrk.o)
 .debug_frame   0x000027e4       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_exit.o)
 .debug_frame   0x00002804       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(getpid.o)
 .debug_frame   0x00002824       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(kill.o)
 .debug_frame   0x00002844       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_check_heap.o)
 .debug_frame   0x00002864       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-errno.o)


Virtual関数を親に持つクラスのインスタンスを生成してみる

サンプル20行目をコメントアウトして再度ビルドすると、以下のようにリンカーでエラーが発生します。

./src/XBee.o:(.rodata._ZTV11XBeeRequest[vtable for XBeeRequest]+0x8): undefined reference to `__cxa_pure_virtual'
./src/XBee.o:(.rodata._ZTV11XBeeRequest[vtable for XBeeRequest]+0xc): undefined reference to `__cxa_pure_virtual'

virutal関連の参照が解決しないと文句を言っているように見えます。ここで、リンカスクリプトのGROUP定義を元に戻して再度コンパイルすとエラーが解消しますが、コードサイズが一気に増大します。

text       data        bss        dec        hex         filename
86876     1424      2368     90668    1622c    LPC1769CppTest.axf

再度mapファイルを見ると、リンクしている関数が山のように増えています。

.debug_frame    0x00000000     0x4288
 .debug_frame   0x00000000       0xc8 ./src/Serial.o
 .debug_frame   0x000000c8       0xac ./src/Timer.o
 .debug_frame   0x00000174     0x1714 ./src/XBee.o
 .debug_frame   0x00001888       0x6c ./src/cr_cpp_config.o
 .debug_frame   0x000018f4      0x158 ./src/cr_startup_lpc176x.o
 .debug_frame   0x00001a4c       0x64 ./src/main.o
 .debug_frame   0x00001ab0       0x4c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_pinsel.o)
 .debug_frame   0x00001afc      0x16c C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_timer.o)
 .debug_frame   0x00001c68      0x2f8 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_uart.o)
 .debug_frame   0x00001f60       0x38 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(system_LPC17xx.o)
 .debug_frame   0x00001f98       0xa0 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_clkpwr.o)
 .debug_frame   0x00002038       0x20 C:\Users\todotani\Documents\LPCXpresso_4.0\workspace\CMSISv2p00_LPC17xx\Debug\libCMSISv2p00_LPC17xx.a(lpc17xx_libcfg_default.o)
 .debug_frame   0x00002058       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(bpabi.o)
 .debug_frame   0x000020a8      0x288 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(unwind-arm.o)
 .debug_frame   0x00002330       0xf4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(pr-support.o)
 .debug_frame   0x00002424       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_divdi3.o)
 .debug_frame   0x00002460       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivdi3.o)
 .debug_frame   0x0000249c       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/thumb2\libgcc.a(_udivsi3.o)
 .debug_frame   0x000024bc       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-abort.o)
 .debug_frame   0x000024e4       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-init.o)
 .debug_frame   0x00002510       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-malloc.o)
 .debug_frame   0x00002540       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mallocr.o)
 .debug_frame   0x0000257c       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcpy.o)
 .debug_frame   0x000025ac       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mlock.o)
 .debug_frame   0x000025dc       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sbrkr.o)
 .debug_frame   0x00002608       0xc0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signal.o)
 .debug_frame   0x000026c8       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-signalr.o)
 .debug_frame   0x00002704       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-freer.o)
 .debug_frame   0x00002754       0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reent.o)
 .debug_frame   0x000027b8       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pure.o)
 .debug_frame   0x000027e0       0x90 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_terminate.o)
 .debug_frame   0x00002870       0x54 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_call.o)
 .debug_frame   0x000028c4       0xd0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_exception.o)
 .debug_frame   0x00002994       0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_arm.o)
 .debug_frame   0x000029f8       0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(fundamental_type_info.o)
 .debug_frame   0x00002a38       0x70 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pointer_type_info.o)
 .debug_frame   0x00002aa8       0x80 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_alloc.o)
 .debug_frame   0x00002b28       0x90 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(tinfo.o)
 .debug_frame   0x00002bb8       0xd0 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(class_type_info.o)
 .debug_frame   0x00002c88       0xb4 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_personality.o)
 .debug_frame   0x00002d3c       0x60 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_throw.o)
 .debug_frame   0x00002d9c       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_globals.o)
 .debug_frame   0x00002dcc       0x6c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_catch.o)
 .debug_frame   0x00002e38       0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_aux_runtime.o)
 .debug_frame   0x00002e78       0xac c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(si_class_type_info.o)
 .debug_frame   0x00002f24       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(bad_cast.o)
 .debug_frame   0x00002f74       0x78 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(pbase_type_info.o)
 .debug_frame   0x00002fec       0x50 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(bad_typeid.o)
 .debug_frame   0x0000303c       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(vterminate.o)
 .debug_frame   0x0000306c       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(eh_type.o)
 .debug_frame   0x00003094      0x48c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libstdc++.a(cp-demangle.o)
 .debug_frame   0x00003520       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_sbrk.o)
 .debug_frame   0x0000354c       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_exit.o)
 .debug_frame   0x0000356c       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(getpid.o)
 .debug_frame   0x0000358c       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(kill.o)
 .debug_frame   0x000035ac       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(_cr_check_heap.o)
 .debug_frame   0x000035cc       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-errno.o)
 .debug_frame   0x000035ec       0x48 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fputc.o)
 .debug_frame   0x00003634       0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fputs.o)
 .debug_frame   0x00003674       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fvwrite.o)
 .debug_frame   0x000036b0       0x58 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fwrite.o)
 .debug_frame   0x00003708       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memchr.o)
 .debug_frame   0x00003734       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memcmp.o)
 .debug_frame   0x00003760       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memmove.o)
 .debug_frame   0x0000378c       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-memset.o)
 .debug_frame   0x000037b8       0x48 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-putc.o)
 .debug_frame   0x00003800       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-realloc.o)
 .debug_frame   0x00003820       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-reallocr.o)
 .debug_frame   0x0000385c       0x64 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-sprintf.o)
 .debug_frame   0x000038c0       0x30 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strcmp.o)
 .debug_frame   0x000038f0       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strcpy.o)
 .debug_frame   0x00003910       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strlen.o)
 .debug_frame   0x00003930       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-strncmp.o)
 .debug_frame   0x0000395c       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-svfprintf.o)
 .debug_frame   0x00003998       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-syswrite.o)
 .debug_frame   0x000039c0       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-wbuf.o)
 .debug_frame   0x000039fc       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-writer.o)
 .debug_frame   0x00003a28       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-wsetup.o)
 .debug_frame   0x00003a54       0x68 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-dtoa.o)
 .debug_frame   0x00003abc       0x40 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fflush.o)
 .debug_frame   0x00003afc      0x114 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-findfp.o)
 .debug_frame   0x00003c10       0x54 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fwalk.o)
 .debug_frame   0x00003c64       0x98 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-locale.o)
 .debug_frame   0x00003cfc       0x34 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-makebuf.o)
 .debug_frame   0x00003d30      0x244 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-mprec.o)
 .debug_frame   0x00003f74       0x28 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-s_fpclassify.o)
 .debug_frame   0x00003f9c       0x80 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-stdio.o)
 .debug_frame   0x0000401c       0x68 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-svfiprintf.o)
 .debug_frame   0x00004084       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-callocr.o)
 .debug_frame   0x000040b0       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-closer.o)
 .debug_frame   0x000040dc       0x3c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fclose.o)
 .debug_frame   0x00004118       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-fstatr.o)
 .debug_frame   0x00004144       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-isattyr.o)
 .debug_frame   0x00004170       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-lseekr.o)
 .debug_frame   0x0000419c       0x2c c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-readr.o)
 .debug_frame   0x000041c8       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(close.o)
 .debug_frame   0x000041e8       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(fstat.o)
 .debug_frame   0x00004208       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(isatty.o)
 .debug_frame   0x00004228       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(lseek.o)
 .debug_frame   0x00004248       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(read.o)
 .debug_frame   0x00004268       0x20 c:/nxp/lpcxpresso_4.1.0_190/lpcxpresso/tools/bin/../lib/gcc/arm-none-eabi/4.5.1/../../../../arm-none-eabi/lib/thumb2\libcr_newlib_nohost.a(write.o)

さっき追加したlibstdc++.aの関数に加えて、libc.aの関数も大量に増えています。殆どはstdio関連の関数で、「こんなの使ってないよ」なやつらばかりです・・


解決策(2012/10/16追記)

audinさんより、__cxa_pure_virtualに対するハンドラーをプロジェクト内で作ってやればリンカーエラーを解消できるとのコメントをいただきました。具体的には、以下のコードをcppファイルのどこかに追加します(今回はcr_startup_lpc176x.cppに追加)。

extern "C" void __cxa_pure_virtual() { while (1); }

__cxa_pure_virtual() はpure virutal function(純粋仮想関数)が呼ばれた場合のエラーハンドラーで、従来はOS環境(ランタイムライブラリ)にて提供されるものと理解。そのため、デフォルトの状態ではランタイム全体がリンクされてしまいコードサイズが肥大化するのですが、__cxa_pure_virtual() を単独で定義してしまえば、「最小構成でコンパイル」したときと同じ関数のみがリンクされるにとどまり、コードサイズを劇的に圧縮できました。

__cxa_pure_virtual() の処理は無限ループですが、純粋仮想関数が呼ばれた時点でプログラムが間違っていますので、エラー処理としてはこれでよいかと。

最終的なコードサイズは以下です:

text       data        bss        dec        hex       filename
20688   1304        520      22512    57f0    LPC1769cpp_Xbee.axf

リンカー関連の設定はデフォルトでOKで、Manage Linker Scriptを有効にしても上記以上にコードサイズが増えることはありませんでした。また、- nostartfilesオプションの有無によるサイズの変化はありませんでした。


まとめ

最初はあきらめモードでしたが、コメントをいただくことによって実用的なコードサイズに圧縮できることが分かりました。そのため、LPCXpresso IDEでのC++プロジェクトの開発は、設定に手間がかかりますが十分可能と思います。

移植したXBee APIモードライブラリはもともとArduino用に開発されたもので、32KB以下のメモリで動かなければならないです。前回のサンプルと同じコードはArduinoでビルドできなかった(コンパイルエラーを解消できず)のですが、APIモードを使ったサンプルをビルドするとコードサイズは6KB程度でした。ArduinoもgccのC++を使っているわけですが半分以下に収まる感じです。対策後のコードでも、「この関数いるのか」みたいなのがいくつかリンクされているように見え、それらを最小限の薄い関数に置き換えるなどすれば、Arduinoのコードサイズに近づけることができるのかもしれません。

このサイトの情報(マイコン風雲録)だとAVRよりLPC2388の方がコードサイズが小さいとあるので、まだ改善の余地はありそうですが、今回はここまでで一段落とします。

上記の実験から、無償版のLPCXpresso IDEでは、マニュアル設定によってC++のプロジェクトを作成・ビルドは可能ですが、親に仮想関数を持つクラスを使うと、一気にコードサイズが増加します。なんとなく、C++で使うnewlibが組み込み用に最適化されていないように思うのですが、原因は分かりません。

この差はライブラリや開発環境の最適化度合いの差でしょうか。LPCXpresso LPC1769でもCの環境だと、FatFsを組み込んだコードで6KB、uIPを使ったコードが9KB程度に収まりますので(Releaseビルドにて)、LPC1769のコードサイズがAVRに比べて明らかに大きいということはないように思います(同一条件の比較ではないですが)。

C++を使いたい場合、Sourcery g++あたりを持ってきて自前で環境を作ったほうがよいということか・・


参考情報

XBee APIモードライブラリのLPCXpressoへの移植

XBeeをAPIモードで使うで紹介したmbed用ライブラリ(オリジナルはArduino用で、Suga koubouさんがmbed用に移植)をLPCXpressoに載せてみました。

オリジナルコードはC++ですが、LPCXpresso IDEでC++のプロジェクトを作成してビルドすることができました。表示部分はMARY OLED基板を使っています。5月にポストした「LPCXpresso LPC1769にMARY拡張基板を乗せる」では、XBeeを載せただけのハリボテ写真を掲載していたのですが、やっと動かすことができました。 

   
LPCXpressoでのC++プロジェクトのビルド

LPCXpresso IDEの新規プロジェクト作成ウイザード(New Project)ではC++プロジェクトが作成できませんが、以下のブログを参考にして、ファイルのコピーやプロジェクトプロパティの設定を行うことによってC++コードのビルドができました。 

マイコン風雲録:LPCXpressoで「C++プロジェクト」を作る方法

私のビルド環境では、LPCXpresso v4.1.0のデフォルトに従って、CMSIS v2をライブラリプロジェクトとして参照していますが、CMSISプロジェクトの設定はREDLIBのままで問題ありませんでした(C++プロジェクト側だけをNEWLIBに変える)。  

   

XBee APIモードライブラリの移植 

主要な変更点は、以下の2つです:  

  • mbed版では、SerialクラスとTimerクラスを使っているため、この部分を自作のクラス(実装は最低限の手抜き)で置き換えています。mbed版はXbeeクラスのコンストラクターにシリアルポートのピン番号を指定しますが、今回の実装はUARTの番号(0~2)を指定します。      
  • オリジナルは、XBee.hで送信ステータスとして”SUCCESS”を#define定義しているのですが、CMSISのlpc_types.hに同じ名前のenum定義があるせいか、lpc_types.hでコンパイルエラーが発生してどうしても解決できなかったため、XBee.h側を”OK”に変更しています。   
ソースコードは以下です(スタートアップコード、や表示用に使ったMARYのコードは再配布が微妙なので含みません)。 

XBee_LPCxpresso.zip

       
サンプルコード 

リモート側(End Device)のXBeeにコマンドを送って、ADC3の読み取りと、DIO1(Digital Outに設定)のトグルによるLチカを行うコードを作ってみました。

LPCXpresso-_XBee

   
#include "XBee.h"
extern "C" {
	#include "oled.h"
	#include "systick.h"
}

/*-- AT command and parameters --*/
uint8_t atISCmd[] = {'I', 'S'};      // Forces a read of all enabled digital and analog input lines
uint8_t atD1Cmd[] = {'D', '1'};		 // DIO1 control
uint8_t atDBCmd[] = {'D', 'B'};      // Received Signal Strength
uint8_t cmdVal0[] = {0};             // Clear RSSI register
uint8_t cmdVal4[] = {4};			 // Digital output, low
uint8_t cmdVal5[] = {5};			 // Digital output, High

/*-- Create instance of Xbee object --*/
XBee xbee(2);
XBeeAddress64 remoteAddress(0x0013A200, 0x406B7111);    // Specify your XBee address

/*-- Create instance of Command and Response object --*/
// Remote ATIS command to read ADC value (ADC3 is enabled by X-CTU tool)
RemoteAtCommandRequest remoteSampleRequest(remoteAddress, atISCmd);
// Remote ATD1 command to turn DIO1 low/high
RemoteAtCommandRequest remoteDIO1_Low(remoteAddress, atD1Cmd, cmdVal4, sizeof(cmdVal4));
RemoteAtCommandRequest remoteDIO1_High(remoteAddress, atD1Cmd, cmdVal5, sizeof(cmdVal5));

// Local ATDB command to read signal strength (RSSI)
AtCommandRequest atDB(atDBCmd);
// Local ATDB0 command to clear RSSI
AtCommandRequest atDB0(atDBCmd, cmdVal0, sizeof(cmdVal0));
// Create instanse to handle command response
AtCommandResponse response = AtCommandResponse();
RemoteAtCommandResponse remoteResp = RemoteAtCommandResponse();


/* Receive command response packet
 * If OK response recieved, return pointer to the Response Data Frame
 */
uint8_t* GetResponse() {
    // Read response
    if (xbee.readPacket(1000)) {
        // Got a response! Check if response is AT command respose
        if (xbee.getResponse().getApiId() == AT_COMMAND_RESPONSE) {
            xbee.getResponse().getAtCommandResponse(response);
            if ( response.getStatus() == AT_OK )
                return response.getValue();
        } else  if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) {
            xbee.getResponse().getRemoteAtCommandResponse(remoteResp);
            if ( remoteResp.getStatus() == AT_OK ) {
                return remoteResp.getValue();
            }
        }
    }

    return 0;
}


/* Get ADC data
 * Data frame structure of ATIS
 * Offset
 *   0   : Number of Samples (Always 1)
 *   1-2 : Digital Channel Mask
 *   3   : Analog Channel Mask
 *   4-5 : Digital Samples (Omit if no DIO enabled)
 *   6-7 : First ADC Data
 */
uint16_t getAnalog(uint8_t *FrameData, int ADC) {
    // ADC data feild starts 4 bytes offest, if no DIO enabled
    uint8_t start = 4;

    // Contains Digital channel?
    if (FrameData[1] > 0 || FrameData[2] > 0) {
        // make room for digital i/o
        start+=2;
    }

    // start depends on how many ADCs before this ADC are enabled
    for (int i = 0; i < ADC; i++) {
        // Is Analog channel Enabled ?
        if ( (FrameData[3] >> i) & 1 ) {
            start+=2;
        }
    }

    return (uint16_t)((FrameData[start] << 8) + FrameData[start + 1]);
}


int main() {
    unsigned int loop = 0;
    Timer t;

    xbee.begin(9600);

    Init_SysTick(10);   // Set systick interval to 10ms
    Init_OLED();

    OLED_printf_Font(OLED_FONT_SMALL);
    OLED_Clear_Screen(OLED_BLK);

    OLED_printf_Position(0, 0);
    OLED_printf_Color(OLED_GRN, OLED_BLK);
    OLED_printf("RSSI:");
    OLED_printf_Position(0, 1);
    OLED_printf_Color(OLED_WHT, OLED_BLK);
    OLED_printf("ADC :");

    while (true) {
        uint8_t *responseVal;
        uint8_t rssiVal = 0;
        uint16_t adcVal = 0;

        // Send ATDB command (Read RSSI register from local Xbee)
        xbee.send(atDB);
        responseVal = GetResponse();
        if ( responseVal != 0 )
            rssiVal = responseVal[0];
        OLED_printf_Position(5, 0);
        OLED_printf_Color(OLED_GRN, OLED_BLK);
        if (rssiVal == 0)
            OLED_printf("No Signal");
        else
            OLED_printf("-%ddBm   ", rssiVal);

        // Clear RSSI register, because Xbee hold RSSI value of last received packet even after radio disconneded
        xbee.send(atDB0);
        GetResponse();

        // Read ADC3 value by sending ATIS command
        xbee.send(remoteSampleRequest);
        responseVal = GetResponse();
        if ( responseVal != 0 ) {
            adcVal = getAnalog(responseVal, 3); // Assume ADC3 is enabled
        }
        OLED_printf_Position(5, 1);
        OLED_printf_Color(OLED_WHT, OLED_BLK);
        if (adcVal == 0)
            OLED_printf("-     ");
        else
            OLED_printf("%x   ", adcVal);

       // Turn DIO1 high/low
       if (loop % 2 == 0) {
    	   xbee.send(remoteDIO1_Low);
       } else {
    	   xbee.send(remoteDIO1_High);
       }
       GetResponse();

       t.start();
       while (t.read_ms() < 1000);
       t.stop();

       loop++;
    }
}

MARY基板用OLEDモジュール(MARY-OB)のライブラリのヘッダファイルを3~4行目でインクルードしていますが、MARY-OBのライブラリはCのコードであるため、extern “C”宣言でくくってやる必要があります。

extern “C”って、意味がよく分かっていなかったのですが、C++のコードからCの関数を呼び出すために、以下の関数はCのだよとC++コンパイラに教えてあげるための記述なんですね。extern “C”なしでは、リンクでundefined referenceエラーが出て、その対処を調べる過程で始めて意味が分かりました。ヤッパリ習うより実践かな。

 

追記

10月8日(土)に@shintamainjpさん主催の「LPCXpresso横浜お楽しみ部会」に参加しました。ネタ切れのおり、MARY拡張基盤を持ち込んでXBeeライブラリの動作を目指したのですが、時間内では動作せず。問題は移植コードでなくXBeeの設定誤りというトホホな内容・・ファームを更新した際に設定内容が初期化されてScan Channelの設定が両端でずれていたことあたりが原因みたいです。とは言え、プロフェッショナルな皆さんとお話ができ、終了後の飲み会も含めて楽く有意義なひと時が過ごせました。

« 2011年7月 | トップページ | 2012年5月 »

2018年10月
  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 31      
無料ブログはココログ