zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.58k stars 6.47k forks source link

fpga: Program FPGA from file in low-memory situations #78809

Open Finomnis opened 5 days ago

Finomnis commented 5 days ago

Is your enhancement proposal related to a problem? Please describe. Our system is an RT1170 combined with a Lattice Crosslink NX FPGA. No external RAM.

This means our system has 1MB RAM. However, the size of the FPGA image is 1.1MB; the FPGA image does not fit into RAM.

It's one valid solution to compile the image into the const data segment, but our FPGA programmers would like to be able to program the FPGA with an image from the FAT filesystem, for experimentation and debugging. This is impossible with the current FPGA API.

Describe the solution you'd like Either add something like

fpga_load_from_file(const struct device *dev, struct fs_file_t* data_file)

or

fpga_load_streamed(const struct device *dev, <some_function_pointer_type>get_more_data_callback, void* user_data, size_t data_size)

to the FPGA api.

Describe alternatives you've considered Bypassing the driver API and calling the FPGA driver implementation directly. While this would work for our own custom-made driver, it will fail for existing Zephyr built-in FPGA drivers. So it would be preferred to have some built-in solution in the FPGA API.

Additional Remarks I would be willed to implement this, but I would like an architectural discussion before stampeding off throwing code around.

cfriedt commented 4 days ago

The current driver implementation supports either loading from RAM or from memory-mapped flash.

However, even without a filesystem, being able to load from unmapped flash would be an improvement.

It would be great to have an RFC / PR for this that can kick start the discussion. Ideally, we wouldn't break backward-compatibility, but I would guess that a new API could be designed that could be used for both cases (contiguous / memory mapped, as well as non-contiguous / non-memory-mapped).

Finomnis commented 4 days ago

In a previous project of mine we had a pretty generic API like this:

fpga_load_streamed(const struct device *dev, <some_function_pointer_type>get_more_data_callback, void* user_data, size_t data_size)

(already mentioned above) where the user initially provides the amount of bytes to be transferred, and the driver then repeatedly queries the callback function to fill a buffer (buffer provided by the driver). We had quite a good experience with this in our own SPI driver (non-Zephyr), as it was perfect for a range of scenarios, like

Although I do understand that if people say this is 'too generic' and 'too bloaty', or whatever, and straight forward 'load fpga from file object' API would be preferrable. Although the code would probably be similar, so exposing more generic funcitionality to the user wouldn't hurt.

cfriedt commented 4 days ago

@Finomnis - would there ever be a case of a short read?

Finomnis commented 3 days ago

@cfriedt I'm unsure what you mean with that :/

cfriedt commented 3 days ago

@cfriedt I'm unsure what you mean with that :/

I guess with the <some_function_pointer_type>get_more_data_callback, there is a possibility that it could be called and it could return fewer bytes than desired, or something along those lines, and then get stuck in a loop, etc.

I guess another possible concern is that an arbitrary function would be called from kernel mode. I wonder if there might be another means of signaling to the driver that more data is available in a shared buffer.

Just trying to look at it from all possible angles.

Finomnis commented 3 days ago

Ah I see. Yeah that all make sense. Maybe a file based approach would be simpler.