1

我刚刚开始深入研究 ARM Cortex-M 微控制器的世界,我决定不使用现有的开发板或易于使用的 IDE,而是直接进入这些东西的裸机,所以我已经将一个 STM32F103 焊接到原型板上,现在我正在尝试使用 Launchpad 中的 gcc-arm-embedded Toolchain 进行工作。在阅读了有关链接器脚本之类的手册之后,我现在编写了自己的链接器脚本和启动代码,它们基本上什么都不做,只是将 .data 部分从 ROM 复制到 RAM,将 .bss 清零,然后调用 SystemInit()从 ST 的标准外设库进行基本的 uC 初始化,最后调用 main()。
现在,从我找到的有关 Cortex M-3 开发的几个教程中,我看到他们使用 -nostartfiles 标志连接器,但现在我想知道:在这种情况下我是否必须自己初始化 newlib?还是我应该使用 GCC/newlib 中的默认启动文件并删除 -nostartfiles?但在这种情况下,我仍然需要进行一些初始化,例如将 .data 复制到 RAM 并设置向量表,这需要自定义链接器脚本。那么我在哪里做呢?
而且我什至不想开始考虑 C++!

那么,初始化这种基于 Cortex-M3 的微控制器及其 libc(不包括外围设备)的推荐方法是什么?

提前致谢!

4

1 回答 1

0

据我所知,您不应该为裸 C 应用程序调用任何 stdlib 函数。但是你应该为 C++ 应用程序,因为有静态初始化程序,RTTI 的 vtable 等等要初始化。据我所知, newlib 本身包含来自 stdlib 的此类函数,例如mem*,*printf等,适用于具有小 ROM 大小的 MCU。

但通常没有什么需要主动初始化的。如果一个标准函数确实有一个全局数据,它希望声明它并将其存储在一些变量中,这些变量存储在该.data部分中。例如__errno,这是一个候选者。但是你不能确定你的 newlib 实现是做什么的,因为由开发人员决定,他们如何在他们的 lib 中设计内部工作流。

看看下面的代码片段。这是一个用 C 编写的启动例程 (Reset-Handler)。ST 将他们的启动文件作为汇编文件 (*.s) 提供,但您也可以在 C 中执行。另一方面,NXP 使用 .c 生成他们的项目启动文件。

如果您的应用程序只是 C 应用程序,则可以省略 C++ 注释下方的函数调用。_data和的符号_idata由链接器生成(在链接器脚本中定义)。

__set_PSP((uint32_t)&_vStackTop);               // set stack pointer
SCB->VTOR = (uint32_t)&VectorTable;             // set the pointer to the vector table

pDest = &_data;
pSrc = &_idata;

// fill .data section
for ( ; pDest < &_edata; )
{
    *pDest = *pSrc;
    ++pSrc;
    ++pDest;
}

// fill .bss section
for (pDest = &_bss; pDest < &_ebss; ++pDest)
{
    *pDest = 0;
}

//
// Call C++ library initialization, if your app is an C++ app
//
__libc_init_array();

main();                                                 // enter main

for(;;)                                                 // you shouldn't land here at anytime
{

}
于 2018-03-20T08:40:20.377 回答