ã»ãšãã©ã®äŸã¯RTOSEmboxã§æ€èšãããããšã«ããã«æ³šæããããšæã ãŸããå®éãQtã OpenCVãªã©ã®è€éãªC ++ãããžã§ã¯ãã¯ããã€ã¯ãã³ã³ãããŒã©ãŒäžã§æ©èœããŸã ãOpenCVã«ã¯å®å šãªC ++ãµããŒããå¿ èŠã§ãããããã¯éåžžãã€ã¯ãã³ã³ãããŒã©ãŒã«ã¯ãããŸããã
åºæ¬æ§æ
C ++èšèªã®æ§æã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠå®è£ ãããŸãããã ããå®è¡æã«ãããã€ãã®åºæ¬çãªãšã³ãã£ãã£ãå®è£ ããå¿ èŠããããŸããã³ã³ãã€ã©ãŒã§ã¯ããããã¯libsupc ++èšèªãµããŒãã©ã€ãã©ãªãŒã«å«ãŸããŠããŸããæãåºæ¬çãªã®ã¯ãã³ã³ã¹ãã©ã¯ã¿ãšãã¹ãã©ã¯ã¿ã®ãµããŒãã§ãããªããžã§ã¯ãã«ã¯ãã°ããŒãã«ãªããžã§ã¯ããšæ°ãããªããžã§ã¯ãã®2çš®é¡ããããŸãã
ã°ããŒãã«ã³ã³ã¹ãã©ã¯ã¿ãšãã¹ãã©ã¯ã¿
C ++ã¢ããªã±ãŒã·ã§ã³ãã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã mainïŒïŒãå ¥åããåã«ããã¹ãŠã®ã°ããŒãã«C ++ãªããžã§ã¯ããã³ãŒãã«ååšããå ŽåãããããäœæãããŸããããã«ã¯ãç¹å¥ãªã»ã¯ã·ã§ã³.init_arrayã䜿çšãããŸããã»ã¯ã·ã§ã³.initã.preinit_arrayã.ctorsããããŸããææ°ã®ARMã³ã³ãã€ã©ã®å Žåãã»ã¯ã·ã§ã³ã®æãäžè¬çãªäœ¿çšæ³ã¯.preinit_arrayã.initãããã³.init_arrayã§ãã LIBCã®èŠ³ç¹ããã¯ãããã¯é¢æ°ãžã®ãã€ã³ã¿ãŒã®éåžžã®é åã§ãããé åã®å¯Ÿå¿ããèŠçŽ ãåŒã³åºãããšã«ãã£ãŠæåããæåŸãŸã§æž¡ãå¿ èŠããããŸãããã®æé ã®åŸãå¶åŸ¡ã¯ã¡ã€ã³ïŒïŒã«ç§»ãããŸãã
Emboxããã°ããŒãã«ãªããžã§ã¯ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºãããã®ã³ãŒãïŒ
void cxx_invoke_constructors(void) {
extern const char _ctors_start, _ctors_end;
typedef void (*ctor_func_t)(void);
ctor_func_t *func = (ctor_func_t *) &_ctors_start;
....
for ( ; func != (ctor_func_t *) &_ctors_end; func++) {
(*func)();
}
}
ããã§ãC ++ã¢ããªã±ãŒã·ã§ã³ã®çµäºãã©ã®ããã«æ©èœããããã€ãŸããã°ããŒãã«ãªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ã®åŒã³åºããèŠãŠã¿ãŸãããã 2ã€ã®æ¹æ³ããããŸãã
ã³ã³ãã€ã©ã§æãäžè¬çã«äœ¿çšãããŠãããã®ããå§ããŸã-__ cxa_atexitïŒïŒïŒC ++ ABIããïŒãä»ããŠãããã¯POSIXatexité¢æ°ã®é¡äŒŒç©ã§ããã€ãŸããããã°ã©ã ã®çµäºæã«åŒã³åºãããç¹å¥ãªãã³ãã©ãŒãç»é²ã§ããŸããäžèšã®ããã«ãã¢ããªã±ãŒã·ã§ã³ã®éå§æã«ã°ããŒãã«ã³ã³ã¹ãã©ã¯ã¿ãŒãåŒã³åºããããšã__ cxa_atexitã®åŒã³åºããéããŠãã³ãã©ãŒãç»é²ããã³ã³ãã€ã©ãŒçæã³ãŒãããããŸããããã§ã®LIBCã®ä»äºã¯ãå¿ èŠãªãã³ãã©ãŒãšãã®åŒæ°ãæ ŒçŽããã¢ããªã±ãŒã·ã§ã³ã®çµäºæã«ããããåŒã³åºãããšã§ãã
å¥ã®æ¹æ³ã¯ããã¹ãã©ã¯ã¿ãžã®ãã€ã³ã¿ãç¹å¥ãªã»ã¯ã·ã§ã³.fini_arrayããã³.finiã«æ ŒçŽããããšã§ãã GCCã³ã³ãã€ã©ã§ã¯ãããã¯-fno-use-cxa-atexitãã©ã°ã䜿çšããŠå®çŸã§ããŸãããã®å Žåããã¹ãã©ã¯ã¿ã¯ãã¢ããªã±ãŒã·ã§ã³ã®çµäºæã«éã®é åºïŒäžäœã¢ãã¬ã¹ããäžäœã¢ãã¬ã¹ãžïŒã§åŒã³åºãå¿ èŠããããŸãããã®æ¹æ³ã¯ããŸãäžè¬çã§ã¯ãããŸãããããã€ã¯ãã³ã³ãããŒã©ãŒã§åœ¹ç«ã€å ŽåããããŸããå®éããã®å Žåãã¢ããªã±ãŒã·ã§ã³ã®ãã«ãæã«ãå¿ èŠãªãã³ãã©ãŒã®æ°ã確èªã§ããŸãã
Emboxããã°ããŒãã«ãªããžã§ã¯ãã®ãã¹ãã©ã¯ã¿ãåŒã³åºãããã®ã³ãŒãïŒ
int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) {
if (atexit_func_count >= TABLE_SIZE) {
printf("__cxa_atexit: static destruction table overflow.\n");
return -1;
}
atexit_funcs[atexit_func_count].destructor_func = f;
atexit_funcs[atexit_func_count].obj_ptr = objptr;
atexit_funcs[atexit_func_count].dso_handle = dso;
atexit_func_count++;
return 0;
};
void __cxa_finalize(void *f) {
int i = atexit_func_count;
if (!f) {
while (i--) {
if (atexit_funcs[i].destructor_func) {
(*atexit_funcs[i].destructor_func)(atexit_funcs[i].obj_ptr);
atexit_funcs[i].destructor_func = 0;
}
}
atexit_func_count = 0;
} else {
for ( ; i >= 0; --i) {
if (atexit_funcs[i].destructor_func == f) {
(*atexit_funcs[i].destructor_func)(atexit_funcs[i].obj_ptr);
atexit_funcs[i].destructor_func = 0;
}
}
}
}
void cxx_invoke_destructors(void) {
extern const char _dtors_start, _dtors_end;
typedef void (*dtor_func_t)(void);
dtor_func_t *func = ((dtor_func_t *) &_dtors_end) - 1;
/* There are two possible ways for destructors to be calls:
* 1. Through callbacks registered with __cxa_atexit.
* 2. From .fini_array section. */
/* Handle callbacks registered with __cxa_atexit first, if any.*/
__cxa_finalize(0);
/* Handle .fini_array, if any. Functions are executed in teh reverse order. */
for ( ; func >= (dtor_func_t *) &_dtors_start; func--) {
(*func)();
}
}
ã°ããŒãã«ãã¹ãã©ã¯ã¿ã¯ãC ++ã¢ããªã±ãŒã·ã§ã³ãåèµ·åã§ããããã«ããå¿ èŠããããŸãããã€ã¯ãã³ã³ãããŒã©çšã®ã»ãšãã©ã®RTOSã¯ãåèµ·åããªãåäžã®ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããŸããéå§ã¯ãã·ã¹ãã å ã§å¯äžã®ã«ã¹ã¿ã é¢æ°mainããå§ãŸããŸãããããã£ãŠãå°ããªRTOSã§ã¯ãã°ããŒãã«ãã¹ãã©ã¯ã¿ã¯äœ¿çšãç®çãšããŠããªãããã空ã§ããããšããããããŸãã
Zephyr RTOSã®ã°ããŒãã«ãã¹ãã©ã¯ã¿ã³ãŒãïŒ
/**
* @brief Register destructor for a global object
*
* @param destructor the global object destructor function
* @param objptr global object pointer
* @param dso Dynamic Shared Object handle for shared libraries
*
* Function does nothing at the moment, assuming the global objects
* do not need to be deleted
*
* @return N/A
*/
int __cxa_atexit(void (*destructor)(void *), void *objptr, void *dso)
{
ARG_UNUSED(destructor);
ARG_UNUSED(objptr);
ARG_UNUSED(dso);
return 0;
}
æ°èŠ/åé€æŒç®å
GCCã³ã³ãã€ã©ã§ã¯ãnew / deleteæŒç®åã®å®è£ ã¯libsupc ++ã©ã€ãã©ãªã«ããããããã®å®£èšã¯ããããŒãã¡ã€ã«ã«ãããŸãã
libsupc ++ããã®new / deleteå®è£ ã䜿çšã§ããŸããAã§ããããããã¯éåžžã«åçŽã§ãããããšãã°ãæšæºã®malloc / freeãŸãã¯ã¢ããã°ãä»ããŠå®è£ ã§ããŸãã
åçŽãªEmboxãªããžã§ã¯ãã®æ°èŠ/åé€å®è£ ã³ãŒãïŒ
void* operator new(std::size_t size) throw() {
void *ptr = NULL;
if ((ptr = std::malloc(size)) == 0) {
if (alloc_failure_handler) {
alloc_failure_handler();
}
}
return ptr;
}
void operator delete(void* ptr) throw() {
std::free(ptr);
}
RTTIãšäŸå€
ã¢ããªã±ãŒã·ã§ã³ãåçŽãªå Žåã¯ãäŸå€ãµããŒããšåçããŒã¿åèå¥ïŒRTTIïŒã¯å¿ èŠãªãå ŽåããããŸãããã®å Žåãã³ã³ãã€ã©ãã©ã°-no-exception-no-rttiã䜿çšããŠç¡å¹ã«ããããšãã§ããŸãã
ãã ãããã®C ++æ©èœãå¿ èŠãªå Žåã¯ãå®è£ ããå¿ èŠããããŸããããã¯ãnew / deleteãããã¯ããã«å°é£ã§ãã
幞ããªããšã«ããããã¯OSã«äŸåãããlibsupc ++ã©ã€ãã©ãªã§ãã§ã«ã¯ãã¹ã³ã³ãã€ã«ãããŠããŸãããããã£ãŠããµããŒããè¿œå ããæãç°¡åãªæ¹æ³ã¯ãlibsupc ++ã䜿çšããããšã§ããã¯ãã¹ã³ã³ãã€ã©ã®ã©ã€ãã©ãªããããã¿ã€ãèªäœã¯ããããŒãã¡ã€ã«ãšã«ãããŸãã
ã¯ãã¹ã³ã³ãã€ã©ã®äŸå€ã䜿çšããã«ã¯ãç¬èªã®C ++ã©ã³ã¿ã€ã ããŒãã¡ãœãããè¿œå ãããšãã«æºããå¿ èŠã®ããå°ããªèŠä»¶ããããŸãããªã³ã«ã¹ã¯ãªããã«ã¯ãç¹å¥ãª.eh_frameã»ã¯ã·ã§ã³ãå¿ èŠã§ãããŸããã©ã³ã¿ã€ã ã䜿çšããåã«ããã®ã»ã¯ã·ã§ã³ãã»ã¯ã·ã§ã³ã®å é ã®ã¢ãã¬ã¹ã§åæåããå¿ èŠããããŸãã Emboxã¯æ¬¡ã®ã³ãŒãã䜿çšããŸãã
void register_eh_frame(void) {
extern const char _eh_frame_begin;
__register_frame((void *)&_eh_frame_begin);
}
ARMã¢ãŒããã¯ãã£ã®å Žåãç¬èªã®æ å ±æ§é ãæã€ä»ã®ã»ã¯ã·ã§ã³ïŒ.ARM.exidxããã³.ARM.extabïŒã䜿çšãããŸãããããã®ã»ã¯ã·ã§ã³ã®åœ¢åŒã¯ããARMã¢ãŒããã¯ãã£ã®äŸå€åŠçABIãïŒEHABIæšæºïŒã§å®çŸ©ãããŠã ãŸãã.ARM.exidxã¯ã€ã³ããã¯ã¹ããŒãã«ã§ããã.ARM.extabã¯äŸå€ãåŠçããããã«å¿ èŠãªèŠçŽ èªäœã®ããŒãã«ã§ãããããã®ã»ã¯ã·ã§ã³ã䜿çšããŠäŸå€ãåŠçããã«ã¯ããªã³ã«ãŒã¹ã¯ãªããã«ããããå«ããå¿ èŠããããŸãã
.ARM.exidx : { __exidx_start = .; KEEP(*(.ARM.exidx*)); __exidx_end = .; } SECTION_REGION(text) .ARM.extab : { KEEP(*(.ARM.extab*)); } SECTION_REGION(text)
GCCããããã®ã»ã¯ã·ã§ã³ã䜿çšããŠäŸå€ãåŠçã§ããããã«ããã«ã¯ã.ARM.exidxã»ã¯ã·ã§ã³ã®éå§ãšçµäºïŒ__exidx_startãš__exidx_endïŒãæå®ããŸãããããã®ã·ã³ãã«ã¯ãlibgcc /unwind-arm-common.incãã¡ã€ã«ã®libgccã«ã€ã³ããŒããããŸãã
extern __EIT_entry __exidx_start;
extern __EIT_entry __exidx_end;
ARMã§ã®ã¹ã¿ãã¯ã¢ã³ã¯ã€ã³ã㮠詳现ã«ã€ããŠã¯ãèšäºãåç §ããŠãã ããã
èšèªæšæºã©ã€ãã©ãªïŒlibstdc ++ïŒ
æšæºã©ã€ãã©ãªã®ãã€ãã£ãå®è£
C ++ã®ãµããŒãã«ã¯ãåºæ¬çãªæ§æã ãã§ãªããlibstdc ++æšæºã©ã€ãã©ãªãå«ãŸããŠããŸãããã®æ©èœãšæ§æã¯ãããŸããŸãªã¬ãã«ã«åããããšãã§ããŸããæååãC ++ setjmpã©ãããŒã®æäœãªã©ã®åºæ¬çãªããšããããŸãããããã¯ãæšæºCã©ã€ãã©ãªãä»ããŠç°¡åã«å®è£ ã§ããŸãããŸããæšæºãã³ãã¬ãŒãã©ã€ãã©ãªïŒSTLïŒãªã©ãããé«åºŠãªãã®ããããŸãã
ã¯ãã¹ã³ã³ãã€ã©ã®æšæºã©ã€ãã©ãª
åºæ¬çãªãã®ã¯Emboxã«å®è£ ãããŠããŸãããããã§ååãªå Žåã¯ãå€éšC ++æšæºã©ã€ãã©ãªãå«ããããšã¯ã§ããŸããããã ããããšãã°ãã³ã³ãããŒã®ãµããŒããå¿ èŠãªå Žåãæãç°¡åãªæ¹æ³ã¯ãã¯ãã¹ã³ã³ãã€ã©ãŒããã®ã©ã€ãã©ãªãŒãšããããŒã»ãã¡ã€ã«ã䜿çšããããšã§ãã
ã¯ãã¹ã³ã³ãã€ã©ããC ++æšæºã©ã€ãã©ãªã䜿çšããå Žåã¯ã²ããããããŸããæšæºã®arm-none-eabi-gccãèŠãŠã¿ãŸãããã
$ arm-none-eabi-gcc -v Using built-in specs. COLLECT_GCC=arm-none-eabi-gcc COLLECT_LTO_WRAPPER=/home/alexander/apt/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/lto-wrapper Target: arm-none-eabi Configured with: *** --with-gnu-as --with-gnu-ld --with-newlib *** Thread model: single gcc version 9.3.1 20200408 (release) (GNU Arm Embedded Toolchain 9-2020-q2-update)
ããã¯ãCæšæºã©ã€ãã©ãªã®--with-newlib.Newlibå®è£ ããµããŒãããŠæ§ç¯ãããŠããŸããEmboxã¯ãæšæºã©ã€ãã©ãªã®ç¬èªã®å®è£ ã䜿çšããŸããããã«ã¯çç±ãããããªãŒããŒããããæå°éã«æããŸãããããã£ãŠãå¿ èŠãªãã©ã¡ãŒã¿ã¯ãæšæºCã©ã€ãã©ãªã ãã§ãªããã·ã¹ãã ã®ä»ã®éšåã«ãèšå®ã§ããŸãã
æšæºCã©ã€ãã©ãªã¯ç°ãªããããã©ã³ã¿ã€ã ãç¶æããããã«äºææ§ã¬ã€ã€ãŒãå®è£ ããå¿ èŠããããŸããã¯ãã¹ã³ã³ãã€ã©ããæšæºã©ã€ãã©ãªããµããŒãããããã«å¿ èŠã§ãããæçœã§ã¯ãªããã®ã®1ã€ã®Emboxããã®å®è£ ã®äŸã瀺ããŸã
struct _reent {
int _errno; /* local copy of errno */
/* FILE is a big struct and may change over time. To try to achieve binary
compatibility with future versions, put stdin,stdout,stderr here.
These are pointers into member __sf defined below. */
FILE *_stdin, *_stdout, *_stderr;
};
struct _reent global_newlib_reent;
void *_impure_ptr = &global_newlib_reent;
static int reent_init(void) {
global_newlib_reent._stdin = stdin;
global_newlib_reent._stdout = stdout;
global_newlib_reent._stderr = stderr;
return 0;
}
libstdc ++ã¯ãã¹ã³ã³ãã€ã©ãŒã䜿çšããããã«å¿ èŠãªãã¹ãŠã®éšåãšãã®å®è£ ã¯ãEmboxã®ãã©ã«ã㌠'third-party / lib / toolchain / newlib_compat /'ã§è¡šç€ºã§ããŸãã
æšæºã©ã€ãã©ãªstd :: threadããã³std :: mutexã®æ¡åŒµãµããŒã
ã³ã³ãã€ã©ã®C ++æšæºã©ã€ãã©ãªã¯ãããŸããŸãªã¬ãã«ã®ãµããŒããæã€ããšãã§ããŸããåºåãããäžåºŠèŠãŠã¿ãŸãããã
$ arm-none-eabi-gcc -v *** Thread model: single gcc version 9.3.1 20200408 (release) (GNU Arm Embedded Toolchain 9-2020-q2-update)
ã¹ã¬ããã¢ãã«ïŒã·ã³ã°ã«ãGCCããã®ãªãã·ã§ã³ã§ãã«ãããããšãSTLããã®ãã¹ãŠã®ã¹ã¬ãããµããŒããåé€ãããŸãïŒããšãã°ã std :: threadããã³ std :: mutexïŒããŸããããšãã°ãOpenCVãªã©ã®è€éãªC ++ã¢ããªã±ãŒã·ã§ã³ã®ã¢ã»ã³ããªã«ã¯åé¡ããããŸããã€ãŸãããã®ããŒãžã§ã³ã®ã©ã€ãã©ãªã¯ããã®æ©èœãå¿ èŠãšããã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããã«ã¯äžååã§ãã
Emboxã§äœ¿çšãããœãªã¥ãŒã·ã§ã³ã¯ããã«ãã¹ã¬ããã¢ãã«ãåããæšæºã©ã€ãã©ãªã®ããã«ç¬èªã®ã³ã³ãã€ã©ãæ§ç¯ããããšã§ããEmboxã®å Žåãposixãã¹ã¬ããã¢ãã«ïŒposixãã䜿çšãããŸãããã®å Žåãstd :: threadããã³std :: mutexã¯ãæšæºã®pthread_ *ããã³pthread_mutex_ *ãä»ããŠå®è£ ãããŸããããã«ãããnewlibäºææ§ã¬ã€ã€ãŒãå«ããå¿ èŠããªããªããŸãã
ãšã³ããã¯ã¹æ§æ
ã³ã³ãã€ã©ã®åæ§ç¯ã¯æãä¿¡é Œæ§ãé«ããæãå®å šã§äºææ§ã®ãããœãªã¥ãŒã·ã§ã³ãæäŸããŸãããåæã«ãå€ãã®æéããããããã€ã¯ãã³ã³ãããŒã©ã§ã¯ããã»ã©å€ããªãè¿œå ã®ãªãœãŒã¹ãå¿ èŠã«ãªãå ŽåããããŸãããããã£ãŠããã®æ¹æ³ãã©ãã§ã䜿çšããããšã¯ãå§ãã§ããŸããã
ãµããŒãã³ã¹ããæé©åããããã«ãEmboxã¯ãããŸããŸãªå®è£ ãæå®ã§ããããã€ãã®æœè±¡ã¯ã©ã¹ïŒã€ã³ã¿ãŒãã§ã€ã¹ïŒãå°å ¥ããŸããã
- embox.lib.libsupcxx-èšèªã®åºæ¬æ§æããµããŒãããããã«äœ¿çšããã¡ãœãããå®çŸ©ããŸãã
- embox.lib.libstdcxx-䜿çšããæšæºã©ã€ãã©ãªã®å®è£ ãå®çŸ©ããŸã
libsupcxxã«ã¯3ã€ã®ãªãã·ã§ã³ããããŸãã
- embox.lib.cxx.libsupcxx_standalone-Emboxã«å«ãŸããåºæ¬çãªå®è£ ã
- third_party.lib.libsupcxx_toolchain-ã¯ãã¹ã³ã³ãã€ã©ã®èšèªãµããŒãã©ã€ãã©ãªã䜿çšããŸã
- third_party.gcc.tlibsupcxx-ãœãŒã¹ããã®ã©ã€ãã©ãªã®å®å šãªã¢ã»ã³ããª
æå°éã®ãªãã·ã§ã³ã¯ãC ++æšæºã©ã€ãã©ãªããªããŠãæ©èœããŸããEmboxã«ã¯ãæšæºCã©ã€ãã©ãªã®æãåçŽãªé¢æ°ã«åºã¥ãå®è£ ããããŸãããã®æ©èœã§ã¯äžååãªå Žåã¯ã3ã€ã®libstdcxxãªãã·ã§ã³ãæå®ã§ããŸãã
- third_party.STLport.libstlportgã¯ãSTLportãããžã§ã¯ãã«åºã¥ãSTLæšæºã©ã€ãã©ãªã§ããgccãåæ§ç¯ããå¿ èŠã¯ãããŸããããããããããžã§ã¯ãã¯é·ãéãµããŒããããŠããŸãã
- third_party.lib.libstdcxx_toolchain-ã¯ãã¹ã³ã³ãã€ã©ã®æšæºã©ã€ãã©ãª
- third_party.gcc.libstdcxx-ãœãŒã¹ããã®ã©ã€ãã©ãªã®å®å šãªã¢ã»ã³ããª
å¿ èŠã«å¿ããŠããŠã£ãã§STM32F7ã§QtãŸã㯠OpenCVããã«ãããŠå®è¡ããæ¹æ³ã«ã€ããŠèª¬æããŠããŸã ããã¹ãŠã®ã³ãŒãã¯åœç¶ç¡æã§ãã