Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

littlefs with async SPI #143

Open
bragma opened this issue Feb 8, 2019 · 10 comments
Open

littlefs with async SPI #143

bragma opened this issue Feb 8, 2019 · 10 comments

Comments

@bragma
Copy link

bragma commented Feb 8, 2019

Hi,
I am considering to use littlefs with an SPI flash, but my SPI driver implementation is totally async. After setting buffers and lengths, I get an event on a callback when the operation is completed. I have no way to implement some "wait for event" to make operations appear as synchronous aside from busy waiting which I prefer to avoid (will not work with other timing constraints, also I have having IRQs and wasting them by having the CPU to poll).
I am new to littlefs, can it work with an async implementation (i.e. start_op -> op_completed_callback) of the required read, prog, erase functions?
Thanks!

@FreddieChopin
Copy link
Contributor

Use an RTOS and then it will be easy to turn your asynchronous code into a synchronous one.

@bragma
Copy link
Author

bragma commented Feb 8, 2019

Use an RTOS and then it will be easy to turn your asynchronous code into a synchronous one.

I'd really like, but I can't do it.

@geky
Copy link
Member

geky commented Feb 8, 2019

Short answer is no, sorry. littlefs is synchronous and adding support for async requires basically rewriting the entire implementation. There's other work littlefs needs that is higher priority.

Though if anyone writes an async implementation, let me know or create a PR :). It would very interesting to compare a sync vs async filesystem implementation.

If you don't want to go full in on an RTOS, you can try using a delimited coroutine library. This would give you the "thread_start" and "thread_yield" functions without preemption. I've heard of several for C (looks like a good list here), though I haven't had a chance to use one yet. They will require porting effort to your MCU though.

Another option I've used before with a lot of success: use low priority interrupts to run a separate async "thread". Then you can run blocking logic on the main thread, with system logic running on the async thread.

@bragma
Copy link
Author

bragma commented Feb 11, 2019

Ok thanks, I'll give a try with protothreads.

@geky
Copy link
Member

geky commented Feb 12, 2019

Hey @bragma, out of curiosity which library are you using? I found this guy, but if I understand protothreads correctly, that won't work for you.

littlefs stores state on the stack, so the threading library you find will need to be able to allocate/save stacks. AFAIK this always requires hardware specific support (for SP).

@bragma
Copy link
Author

bragma commented Feb 12, 2019

At the moment I am working on a barebone firmware for Nordic nrf52832. There are a few options available, but to summarize the firmware is just using the main context and interrupts. The problem with this setup is that all peripheral accesses are async, with a pattern like this:

init_driver(event_handler) -> setup the driver to call the operation completed handler

start_device_operation() -> operation is started and function returns
...
event_handler() is called via IRQs

One trivial way to make this behave as an sync operation is to set/clear a flag before starting and at completion of an operation, and in the main thread busy wait on it. But the problem is that busy waiting wastes battery power. The busy wait cycle should instead put the device on sleep, but I've found it is not trivial to do when also handling radio and other events...

There is a basic scheduler to use from IRQs to move back to the main thread, but it uses a queue and an event handler which basically moves the async problem to another level.

@geky
Copy link
Member

geky commented Feb 12, 2019

Do you have the __WFI() intrinsic in your compiler? That will tell the processor it can sleep until it recieves an interrupt. I may be misunderstanding the issue.

@bragma
Copy link
Author

bragma commented Feb 12, 2019

You have not misunderstood, there is also __WFE() but it is not enough when using SoftDevice for radio due to some critical timing constraints. Normally sd_app_evt_wait() is used and things become more tricky due to its internals.

@geky
Copy link
Member

geky commented May 22, 2019

I couldn't find a coroutine library that did exactly what I wanted (easy to port, MCU support), so I wrote my own: https://github.com/geky/coru

I realized this old, but if you're still needing an async API, coru may be useful. There's a littlefs example in the readme. : )

@Inviz
Copy link

Inviz commented Jan 2, 2023

Is there an understanding of how much stack memory littlefs requires? I wonder if initial setup of FS requires more memory too?

Update: #417 Looks like ~ 1300b

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants