不能在stm32的嵌入式c中使用sleep()
cant use sleep() in embedded c for stm32
我尝试学习用于 stm32 微控制器的嵌入式 c。我试着编写一个简单的闪烁程序,我在其中使用了 sleep() 函数。
代码:
/* Includes ------------------------------------------------------------------*/
#include <unistd.h>
#include "main.h"
int main(void)
{
HAL_Init();
while (1)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
sleep(1); // this line throws a error, when compiling
}
}
编译器给我以下错误:
/usr/lib/gcc/arm-none-eabi/7.4.0/../../../../arm-none-eabi/bin/ld: CMakeFiles/untitled2.elf.dir/Src/main.c.obj: in function `main':
/home/heinrich/CLionProjects/untitled2/Src/main.c:106: undefined reference to `sleep'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/untitled2.elf.dir/build.make:391: untitled2.elf] Fehler 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/untitled2.elf.dir/all] Fehler 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/untitled2.elf.dir/rule] Fehler 2
make: *** [Makefile:118: untitled2.elf] Fehler 2
我想,问题是一个没有安装的库,但我在 fedora-repos for arm-gcc 中安装了所有东西
OS:软呢帽 30
IDE:克利昂
工具链:arm-gcc-none-eabi
您不能在带有 arm-none-eabi-gcc 编译器的裸机目标上使用 POSIX 函数。没有操作系统。没有sleep()
、gettimeofday()
、clock_gettime()
、getpid()
、fork()
、stat()
、open()
、pthread_create()
以及许多其他 C 和 posix 以及 *unix 特定的函数。这些函数的声明可以在标准头文件中找到,但链接器会因 undefined reference
错误而放弃。你必须自己实现它们。
您的编译器 arm-none-eabi-gcc 默认使用 newlib C 标准库的实现。它带有最基本的和非操作系统感知功能的实现,例如 snprintf
和 mktime
。对于 printf
或 putc
之类的函数,应实施回调 _write()
或 _write_r()
以使它们起作用。要使 malloc()
正常工作,您必须提供 sbrk()
。对于大多数其他功能,您必须自己实现它们。
常用的 -specs=nosys.specs
编译器选项仅指定使用 "default" 一些函数的非系统实现,例如 fseek()
或 write()
或 sbrk()
.这些函数中的大多数只是 return -1
并将 errno 设置为 ENOSYS
,但是它们在那里,以便您可以编译程序。可以找到实现 here.
如果你恰好使用了stm32 hal库,你可以将你的systick中断初始化为1ms并使用stm32世界中的标准HAL_Delay()
函数并提供你自己的实现sleep()
:
unsigned int sleep(unsigned int seconds) {
HAL_Delay(seconds * 1000);
return 0;
}
反之亦然,即在您的设备上使用可实现这些功能的操作系统。例如有RIOT OS旨在提供POSIX兼容性并且已经提供了很多调用。
微控制器可能不包含标准库,因此在这种情况下,您必须自己编写缺少的函数。例如睡眠可以这样实现:
void my_sleep(int secs) {
#define STEPS_PER_SEC 650000000
unsigned int i,s;
for (s=0; s < secs; s++) {
for (i=0; i < STEPS_PER_SEC; i++) {
// skip CPU cycle or any other statement(s) for making loop
// untouched by C compiler code optimizations
asm("nop");
}
}
}
int main() {
my_sleep(1);
}
顺便说一下,常量 STEPS_PER_SEC
应该根据您的控制器 CPU 规格和您的编译模式(优化开/关等)根据经验进行调整。
我尝试学习用于 stm32 微控制器的嵌入式 c。我试着编写一个简单的闪烁程序,我在其中使用了 sleep() 函数。
代码:
/* Includes ------------------------------------------------------------------*/
#include <unistd.h>
#include "main.h"
int main(void)
{
HAL_Init();
while (1)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin);
sleep(1); // this line throws a error, when compiling
}
}
编译器给我以下错误:
/usr/lib/gcc/arm-none-eabi/7.4.0/../../../../arm-none-eabi/bin/ld: CMakeFiles/untitled2.elf.dir/Src/main.c.obj: in function `main':
/home/heinrich/CLionProjects/untitled2/Src/main.c:106: undefined reference to `sleep'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/untitled2.elf.dir/build.make:391: untitled2.elf] Fehler 1
make[2]: *** [CMakeFiles/Makefile2:73: CMakeFiles/untitled2.elf.dir/all] Fehler 2
make[1]: *** [CMakeFiles/Makefile2:85: CMakeFiles/untitled2.elf.dir/rule] Fehler 2
make: *** [Makefile:118: untitled2.elf] Fehler 2
我想,问题是一个没有安装的库,但我在 fedora-repos for arm-gcc 中安装了所有东西
OS:软呢帽 30 IDE:克利昂 工具链:arm-gcc-none-eabi
您不能在带有 arm-none-eabi-gcc 编译器的裸机目标上使用 POSIX 函数。没有操作系统。没有sleep()
、gettimeofday()
、clock_gettime()
、getpid()
、fork()
、stat()
、open()
、pthread_create()
以及许多其他 C 和 posix 以及 *unix 特定的函数。这些函数的声明可以在标准头文件中找到,但链接器会因 undefined reference
错误而放弃。你必须自己实现它们。
您的编译器 arm-none-eabi-gcc 默认使用 newlib C 标准库的实现。它带有最基本的和非操作系统感知功能的实现,例如 snprintf
和 mktime
。对于 printf
或 putc
之类的函数,应实施回调 _write()
或 _write_r()
以使它们起作用。要使 malloc()
正常工作,您必须提供 sbrk()
。对于大多数其他功能,您必须自己实现它们。
常用的 -specs=nosys.specs
编译器选项仅指定使用 "default" 一些函数的非系统实现,例如 fseek()
或 write()
或 sbrk()
.这些函数中的大多数只是 return -1
并将 errno 设置为 ENOSYS
,但是它们在那里,以便您可以编译程序。可以找到实现 here.
如果你恰好使用了stm32 hal库,你可以将你的systick中断初始化为1ms并使用stm32世界中的标准HAL_Delay()
函数并提供你自己的实现sleep()
:
unsigned int sleep(unsigned int seconds) {
HAL_Delay(seconds * 1000);
return 0;
}
反之亦然,即在您的设备上使用可实现这些功能的操作系统。例如有RIOT OS旨在提供POSIX兼容性并且已经提供了很多调用。
微控制器可能不包含标准库,因此在这种情况下,您必须自己编写缺少的函数。例如睡眠可以这样实现:
void my_sleep(int secs) {
#define STEPS_PER_SEC 650000000
unsigned int i,s;
for (s=0; s < secs; s++) {
for (i=0; i < STEPS_PER_SEC; i++) {
// skip CPU cycle or any other statement(s) for making loop
// untouched by C compiler code optimizations
asm("nop");
}
}
}
int main() {
my_sleep(1);
}
顺便说一下,常量 STEPS_PER_SEC
应该根据您的控制器 CPU 规格和您的编译模式(优化开/关等)根据经验进行调整。