Git Product home page Git Product logo

Comments (7)

vsergeev avatar vsergeev commented on July 16, 2024

I also like the simplicity of stack allocations, and c-periphery had this exact memory model in v1.x.x, but it was abandoned in v2.x.x because the GPIO handle state grew to be too complex when character device GPIO support was added (see https://github.com/vsergeev/c-periphery/blob/v2.2.2/src/gpio.c#L60). Using opaque pointers also has the benefit of a cleaner API and the ability to build c-periphery into a shared library with well-defined ABI compatibility and versioning. It was one of the main reasons the major version changed from 1 to 2.

Since c-periphery is always going to be running in a Linux environment and not a bare metal environment, I think a heap allocation in userspace for a couple of bytes is really not that big of a deal, and it makes it easier to share c-periphery handles out of the box in more complex software (i.e. without a user malloc).

There's no plans to go back to the old memory model for the reasons above. It might be possible to create a macro wrapper using alloca() for a stack allocated handle, e.g.:

size_t spi_handle_size(void);
spi_t *spi_init(spi_t *handle);
#define spi_new_alloca() spi_init(alloca(spi_handle_size()))
...

int main(void) {
    spi_t *spi = spi_new_alloca();
    ...
}

but I don't know if it's really worth adding that complexity to the API.

from c-periphery.

Livius90 avatar Livius90 commented on July 16, 2024

You do not have to change your official concept, it could be just an alternative memory model which can used also, if you move that handle declarations in the header files. If the gpio, spi etc handle declarations would be in .h files it can be a user choose which one to use it, alloc it via spi_new() as in your example, or use it from stack as i mentioned in an example.

For example, i started a C++ wrapper class for your c-periphery spi and gpio and it would be nice to use it without calloc for easy and safe/quick using.

from c-periphery.

vsergeev avatar vsergeev commented on July 16, 2024

The issue is that the exposed handle structures become a part of the ABI and make versioning the shared library more difficult. If the handle structure is exposed and a field is added or removed, it would require a major version number change and break existing dynamically linked software. On the other hand, if the handle is opaque, modifying its fields wouldn't require a major version number change, since the library itself is creating it with the right members and size.

If we were confident the handle structure would never change, then maybe it would be OK to expose them. Providing a handle size getter and using alloca() is a compromise, but I suspect you probably want to declare handles as a POD instance within a class.

from c-periphery.

Livius90 avatar Livius90 commented on July 16, 2024

This is my goal in my SPI class but now it works only with spi_t* spi and this->spi = spi_new().

class SPI {
private:
	spi_t spi;
	bool is_open;
public:
	SPI(string spi_path, unsigned int mode, uint32_t max_speed, string bit_order, uint8_t bits_per_word, uint8_t extra_flags);
	/* constructor, methods, etc */ 
}

from c-periphery.

vsergeev avatar vsergeev commented on July 16, 2024

I don't think I understand the underlying issue -- what's the problem in your example with using spi_t *spi; and spi_new()?

from c-periphery.

Livius90 avatar Livius90 commented on July 16, 2024

I can allocate my SPI class on stack, and if i can allocate spi_t spi; in stack too, it could be very fast when the spi_transfer() function want to access it frequently.

from c-periphery.

vsergeev avatar vsergeev commented on July 16, 2024

I'm not certain there is a measurable concern here. The time spent in the ioctl() system call of spi_transfer() is going to dwarf any time spent accessing the fd in the spi_t structure on the heap or on the stack, or even the one-time call to malloc(). As you probably know, the SPI transfers are much much slower than any of these operations. If you're worried about the latency introduced by malloc() before the transfer begins, it's likely in the noise compared to any timing guarantees of I/O done from userspace Linux.

from c-periphery.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.