Reputation: 49
I try to learn embedded c for a stm32-microcontorller. I try to wirte a easy blink program, where i use the sleep()-function.
code:
/* 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
}
}
the compiler gives me following error:
/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
I think, the problem is a not-installed libary, but i installed everything in the fedora-repos for arm-gcc
OS: Fedora 30 IDE: CLion Toolchain: Arm-gcc-none-eabi
Upvotes: 3
Views: 11447
Reputation: 11277
Micro-controller may not have standard library included, so in this case you must roll your own missing functions. For example sleep could be implemented like this:
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);
}
Btw constant STEPS_PER_SEC
should be adjusted empirically according to your controller CPU specs and your compilation mode (optimizations On / Off, etc.).
Upvotes: 3
Reputation: 141493
You can't use POSIX functions on bare-metal target with arm-none-eabi-gcc compiler. There is no operating system. There is no sleep()
, gettimeofday()
, clock_gettime()
, getpid()
, fork()
, stat()
, open()
, pthread_create()
and many, many, many others C and posix and *unix specific functions. The declarations of these functions can be found in the standard headers, but linker will just give up with undefined reference
error. You have to implement them yourself.
Your compiler arm-none-eabi-gcc by default uses newlib implementation of C standard library. It comes with an implementation of most basic and not operating system aware functions, like snprintf
and mktime
. For functions like printf
or putc
the callback _write()
or _write_r()
should be implemented for them to work. For malloc()
to work you have to provide sbrk()
. For most other functions, you have to implement them yourself.
The commonly used -specs=nosys.specs
compiler option just specifies to use a "default" no-system implementation of some functions like fseek()
or write()
or sbrk()
. Most of these functions just return -1
and set errno to ENOSYS
, but are there, so that you can compile your program. The implementation can be found here.
If you happen to use stm32 hal library, you can initialize your systick interrupt for 1 ms and use the standard in stm32 world HAL_Delay()
function and provide your own implementation of sleep()
:
unsigned int sleep(unsigned int seconds) {
HAL_Delay(seconds * 1000);
return 0;
}
The other way round is to use an operating system on your device that provides an implementation of these functions. For example there is RIOT OS that aims at providing POSIX compatibility and already provides many calls.
Upvotes: 8