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

Potential DMA overhaul/rethink/cleanup discussion #170

Open
usbalbin opened this issue Jan 13, 2025 · 13 comments
Open

Potential DMA overhaul/rethink/cleanup discussion #170

usbalbin opened this issue Jan 13, 2025 · 13 comments

Comments

@usbalbin
Copy link
Member

usbalbin commented Jan 13, 2025

Thought I would make an issue to have somewhere to discuss

Some prior art

Doc

cc @AdinAck

@usbalbin
Copy link
Member Author

I have quite limited experiance with DMA so take this with a grain of salt but here are some of the use cases I think might be nice to support:

  1. DMA for collecting ADC samples. Might for example be useful when the ADC is triggered by hardware and timing is very important like measuring at specific points in the switch period of a DC/DC converter, still letting the processor do other things at the same time.
  2. UART Tx. Send an entire message asyncronously
  3. UART Rx. Receive an entire message asyncronously (how do we know when to stop? timeout, msg len, etc?)
  4. more?

@AdinAck
Copy link
Contributor

AdinAck commented Jan 13, 2025

  1. Yes I believe G0 has an example of this.
  2. To be a bit more specific, send messages of differing lengths one after the next.
  3. There are two ways (Embassy has both):
    • Receive until idle line
    • Receive until receive buffer full
  4. A peripheral to peripheral example would be nice. (ADC -> FMAC ?)

@usbalbin
Copy link
Member Author

usbalbin commented Jan 13, 2025

  1. A peripheral to peripheral example would be nice. (ADC -> FMAC ?)

Would that mean that you could have the entire control loop running in FMAC? So for example ADC -> FMAC(for example pid IIR regulator) -> PWM-duty, with the help of DMA?

Something along those lines might be done in AN5788

@AdinAck
Copy link
Contributor

AdinAck commented Jan 13, 2025

Interesting idea! I have never used the FMAC so I don't know if this is within it's capabilities. I was just thinking denoising an ADC signal before serving it to the CPU, but if the FMAC can facilitate a PID loop for the duty cycle of a timer that would be an awesome example to provide!

@usbalbin
Copy link
Member Author

usbalbin commented Jan 13, 2025

Reading an5497 page 51 they seem to "only" have the DMA transfer from ADC to FMAC and then trigger an interrupt which does some clamping and then passes the value along.

@usbalbin
Copy link
Member Author

Table 9 of AN5788 gives some performance numbers on regulator in software vs in FMAC

@AdinAck
Copy link
Contributor

AdinAck commented Jan 13, 2025

Yeah those numbers make sense, I kind of expected the performance improvement to be much greater (like CORDIC) but I guess filtering takes a long time even when done by a dedicated co-processor. Still would be a good DMA example.

@usbalbin
Copy link
Member Author

  1. To be a bit more specific, send messages of differing lengths one after the next.

Could something like next_transfer described in #171 solve this use case?

@AdinAck
Copy link
Contributor

AdinAck commented Jan 15, 2025

I really don't have enough information to say right now. It might be some time before I have enough experience with DMA to speak to any design choices. I am thinking on it but I don't have any answers yet.

It likely would be a step in the right direction, though.

@AdinAck
Copy link
Contributor

AdinAck commented Feb 4, 2025

Just spitballing here (@usbalbin let me know what you think of this). What if transfers were split into sources and sinks? For example, sending bytes over UART, the USART peripheral would take ownership of the sink (or the sink take ownership of the USART) (hopefully the USART can also be split into Tx and Rx) and then the user can write to the source whenever they want. It could even implement fmt::Write (like USART currently does). Under the hood we would just change the DMA source address to whatever slice was passed in, and check if a transfer is currently in progress already, so it would be try_write I guess. The slice passed would need a static lifetime, of course, and would probably need to be taken as a shared reference. I know the current implementation uses an exclusive reference but I don't think that is necessary.

Do please poke holes in this idea.

@usbalbin
Copy link
Member Author

usbalbin commented Feb 4, 2025

What use case would splitting the source from the sink open up that would not be possible with one single type(Tx<Dma>, or DmaTransfer<Tx> in the mem to peripheral case(or reverse)?

Oh, that would probably help with peripheral to peripheral transfers right?

@AdinAck
Copy link
Contributor

AdinAck commented Feb 4, 2025

Yeah good point, I guess it could be one type. But you're right for p-p it could be useful, I hadn't thought of that.

Nonetheless, split or not, I think designing an interface with a try_write(src: &'static [Transfer::Word]) -> Result<(), Transfer::Error> would make sense.

An async interface could accept a non-static reference.

@AdinAck
Copy link
Contributor

AdinAck commented Feb 4, 2025

Ah, I guess this is reminiscent of a "oneshot" transfer, perhaps that could be a type-state of Transfer which exposes the appropriate interface (circular vs oneshot).

Edit: It's kind of almost set up like that but the interfaces exposed don't seem appropriate.

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

2 participants