-
Notifications
You must be signed in to change notification settings - Fork 231
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
Add halfway interrupts for SLINK interface #122
Comments
Good example! I did not think about this when implementing the SLINK. But it makes sense. So I agree that the IRQ conditions should be changed. However, there is a problem: there is only one global TX interrupt. So if this interrupt indicates "TX FIFO half full" how does the software check which link's FIFO actually caused this interrupt? Right now there are only status flags that indicate if a certain TX is ready to send (so if the FIFO can take more data). There is the same problem with the global RX interrupt. We could change the status flags or we could add more status flags that also indicate if a certain FIFO is half-full. 🤔 |
Assuming that there would just be more status bits, what would be the current behaviour if, while the interrupt was being serviced, a separate tx halfway interrupt occurred? Are all of the status bits just ORed into the global interrupt line? If no interrupts would be missed, then I think just adding more status bits would be ok, splitting all of the status bits into their own 32 bit register perhaps? I think having a configurable threshold rather than halfway is probably also useful for future proofing. I had a look at some STM32 data sheets with ethernet peripherals (where this functionality is common and often necessary) and they all had configurable levels with no fixed halfway interrupt. But this is obviously more costly in terms of registers as one would need to store the threshold. |
Yes and no. The status flags are checked for edges and then they are OR-ed to generate the interrupt request. So if any FIFO fulfills the IRQ condition at any time an IRQ is generated.
Right now we have the following behavior: If a SLINK interrupt is being serviced right now, one more SLINK IRQ can trigger and will be queued until the current IRQ service handler has finished. I see that this might not be optimal. The current SLINK was build for hardware simplicity - the RX/TX interrupts just indicate "that something has happened" and it is up to the software to check which RX/TX links actually rang the interrupt.
I agree that this feature comes handy! But I think I would prefer to allow customization during a pre-synthesis constant where the default level is "half full". Furthermore, I think this is something to be configured via a constant in the package and not via a generic as it is a more specific option and the entity is already quite complex 😅 |
I have been thinking about this a little today, and I agree with you. I can't think of a realistic example where you would need to change this threshold at runtime. So pre-synthesis sounds like a good idea (I guess also powers of two to simplify the logic). The interrupt problem is tricky. I believe the way this is handled on STM32s (as far as I can recall) is that the interrupts are level triggered, not edge triggered. So the interrupt will constantly fire unless the status register bit is cleared or the interrupt is masked off, and it is the responsibility of the software to somehow do one of these two things. If you perform some action to clear the status bit and then the event occurs again while the interrupt is running, it will run the interrupt a second time. |
👍 Do you think it is better to have per-link configurations or just one global configuration for the FIFO-level IRQ?
I tried to avoid level-sensitive interrupts for the CPU core. The CPU supports nested interrupts so a level-sensitive interrupt being high all the time could cause a deadlock (in the hardware!) if no care is taken by the software programmer. How about this (this is quite close to your proposal):
Then, the interrupt service handler has to...
|
Yes, this approach sounds good to me. |
I thought about this again and I think that there is no need to provide an option to specify the FIFO fill level that triggers an interrupt. I think it is sufficient to always use "half-full" as trigger level. If an application requires a different level you could still add an external FIFO that asserts its "free" signal if its fill level has fallen below the custom level (in case of a TX link). |
SLINK now provides FIFO half-full interrupts
added functions to check FIFO half-full fill level
I have reworked the SLINK interrupt system according to the discussion above. It was tested in simulation and with a very simple hardware setup, but I do not have a real application for verification of all aspects yet. I think the FOMU setups + a more sophisticated USB bridge (#102) might be a good real world test scenario. |
Looks good! I think USB data transfer is a good test case also. |
I think this can be closed. |
Describe the solution you'd like
The following text is in the documentation for the SLINK peripheral.
Given that the TX and RX buffers can be quite long (up to 32k), it would be useful to have a halfway interrupt available so that more data can be computed.
An example scenario is when using a DAC at a fixed sample rate to generate some complex, non-periodic waveform where the samples are computed by the software; the TX empty interrupt is not enough, as this is too late. It means that the DAC will likely have to stall or have some conversions with no data.
Perhaps one other option would be to allow the user to specify the position of it, either by generics or at runtime.
Additional context
I wouldn’t necessarily expect this to be enabled by default.
The text was updated successfully, but these errors were encountered: