-1

I'm trying to use the stat() function in the `#include <sys/stat.h> library however whenever I call it I get this error:

...toolchains/gcc-arm-none-eabi-8-2018/arm-gcc-macos/arm-none-eabi/lib/thumb/v6-m/nofp/libc_nano.a(lib_a-statr.o): in function `_stat_r':
statr.c:(.text._stat_r+0xe): undefined reference to `_stat'

Here is my file (I've listed all my includes, I know some might be not related to this problem but just incase I've listed all):

#include <kernel.h>
#include <device.h>
#include <drivers/i2c.h>
#include <sys/__assert.h>
#include <logging/log.h>
#include <sys/printk.h>
#include <soc.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define SOURCE_FILE   "battery.gm.fs"

int write_to_dev(struct device* dev)
{
    struct stat st;
    int nSourceFile;
    char *pFileBuffer;

    stat(SOURCE_FILE, &st); // problematic line
    // other code here
}

Whenever I call write_to_dev() I'm getting this issue. I'm basing my code off page 17 of this link: https://www.ti.com/lit/an/slua801/slua801.pdf?ts=1595360845070&ref_url=https%253A%252F%252Fwww.google.com%252F Thanks for your help!

Edit: I'm using an STM32 chip with zephyr RTOS, and TI BQ27621 fuel gauge

PurpleSpark
  • 63
  • 1
  • 10
  • Maybe this answer can help you: [Answer](https://stackoverflow.com/a/44320282/11023871) – David Buzatu Jul 21 '20 at 19:50
  • @PurpleSpark: Is it a baremetal or any Embedded Linux processor? Please specify which specific TI Processor or Controller you are using. – Gaurav Pathak Jul 21 '20 at 19:51
  • @GauravPathak It's on a STM32 processor. I'm using the Zephyr RTOS. I'll update my question with this too – PurpleSpark Jul 21 '20 at 19:52
  • @PurpleSpark: Code on page 17 is meant for Linux user space application, it is not for baremetal pure firmware. – Gaurav Pathak Jul 21 '20 at 20:03
  • You should show how you built your code (compile/link commands and options). – lurker Jul 21 '20 at 20:04
  • 2
    So, no, there is no `stat`on your platform, your platform environment doesn't implement posix nor other operating system standards, there is no underlying filesystem and it just makes no sense. Zeprhy [can be configured](https://docs.zephyrproject.org/latest/guides/portability/posix.html) to support a meaningful subset of posix functions, but for I/O you have to implement them yourself. Where do you expect the file `"battery.gm.fs"` to be located? In flash? In ram? In external sd card? – KamilCuk Jul 21 '20 at 20:06
  • @KamilCuk Sorry I'm new to this space - do you mind explaining to me how you found out that my platform doesn't support it? And I want `battery.gm.fs` to be located in RAM. – PurpleSpark Jul 21 '20 at 20:11
  • `And I want` So implement it. `how you found out that my platform doesn't support it?` Well..it's easier to explain where something is, rather then it's missing from everywhere. Because you get undefined reference, the symbol is missing. But maybe it's the familiarity with zephyr, newlib, embedded and bare metal development and freestanding environment. – KamilCuk Jul 21 '20 at 20:16
  • If you intent to implement the [POSIX I/O primitives](https://pubs.opengroup.org/onlinepubs/9699919799/) on your [freestanding environment](https://stackoverflow.com/questions/30825151/is-there-a-meaningful-distinction-between-freestanding-and-hosted-implementation) (or not so freestanding, as you include zephyr) I recommend to get to know [how to port newlib](https://www.google.com/search?q=porting+newlib) as most probably you'll end up using [newlib as an implementation of C standard library](https://en.wikipedia.org/wiki/C_standard_library#Implementations) (zephyr can use it's own I think) – KamilCuk Jul 21 '20 at 20:25
  • STM32 is a very extensive range of MCUs. Can you be more specific? And does your system have additional components such as external flash, external RAM, SD card etc. connected to the MCU? – Codo Jul 21 '20 at 20:40
  • @Codo what will it change? STM32 except M2 which is a application processor + uC do not implement it. – 0___________ Jul 21 '20 at 20:54
  • @Codo I'm using the stm32g0316 mcu. No I won't have any additional peripherals – PurpleSpark Jul 21 '20 at 20:57
  • @P__J__ Just making sure it's not an unusual setup. I agree: no I/O subsystem, no file system, no POSIX functions, no `_stat()`. @PurpleSpark The source code you have copied was written for a completely different league of systems: Linux system with a file system and a decent amount of RAM vs a STM32 MCU with a super minimal operating system, very limited RAM and no file system. – Codo Jul 21 '20 at 21:18
  • @PurpleSpark You can forget almost everything you learned about programming in Linux. 3/4 of the include files from your code will have to be deleted.. Forget about file systems (unless you implement one), forget about dynamic memory allocation and many other features. uC toolchains usually implement only minimal set of the functions. Some may be present as a stubs only. – 0___________ Jul 21 '20 at 21:35
  • @Codo does that mean that `fopen()` from `#include` also won't work? I'm trying to read in files using that and it's giving me `errno` as 0 but I'm not sure how to interpret that because 0 is the default. – PurpleSpark Jul 21 '20 at 22:18
  • @P__J__ This is from my board's datasheet: `It also includes optional interfaces for middleware components comprising a TCP/IP stack and a Flash file system.` Doesn't this mean that it does have a file system? – PurpleSpark Jul 21 '20 at 23:39
  • I'm not very familiar with Zephyr OS. It might include part of *stdio* to support string formatting (*sprintf*) etc. But your device has no file system and no files. So `fopen()` makes no sense. – Codo Jul 22 '20 at 05:55
  • @PurpleSpark `fopen` will not work. toy can for example add fatfs (from chan) support or lwip. – 0___________ Jul 22 '20 at 09:07

1 Answers1

0

The example code you are trying to port to your device was written for a Linux system (e.g. for a Raspberry Pi). Such a system is much more capable than your MCU board: it has a full-blown operating system, file system and files and the necessary I/O operations. You can still get the relevant parts to run on your board using Zephyr OS:

End-system dependent APIs

Implement the functions gauge_read, gauge_write and gauge_address is required and described by the TI document. It should be rather straight-forward as it is mainly a wrapper for the I2C communication. Zephyr provides the required I2C functions.

Now the files gauge.c and gauge.h should compile.

FlashStream initialization

The sample code uses file system operations to retrieve a file (in FlashStream format) to initialize the sensor. The parser for the file format is part of gauge.c and takes a string (text file contents) as input. So it does not depend on file system operations.

I've never used such a sensor but my guess is the initialization file is short and can be easily embedded as a string. So create the initialization file, open it as a text file and copy the contents into your program:

const char* fs =
    "W: AA 3E 02 00\n"
    "C: AA 3E 02 00 02 20 00 03\n"
    "W: AA 3E 02 00\n";

Now you can initialize the sensor:

gauge_execute_fs(pHandle, fs);

The file system code (stat(), fopen() etc.) is no longer needed and can be removed. Your program should now compile and build.

Codo
  • 75,595
  • 17
  • 168
  • 206
  • Thanks @Codo. I gave up on using `stat()1` and `fopen()` and just put everything in a `#define` in my program. I think it's the easiest way to go from here out. – PurpleSpark Jul 22 '20 at 15:34