Improvements for dcd_transdimension#1062
Conversation
hathach
left a comment
There was a problem hiding this comment.
thank you for your great PR as usual. Though can you explain a bit for the usage of ptr wrap in the qtd_init_fifo()
| // Set linear part | ||
| uint8_t i = 1; | ||
| for(; i<5; i++) | ||
| { | ||
| if (len_lin <= 0) break; | ||
| p_qtd->buffer[i] |= tu_align4k( p_qtd->buffer[i-1] ) + 4096; | ||
| len_lin -= 4096; | ||
| } | ||
| // Set wrapped part | ||
| for(uint8_t page = 0; i<5; i++, page++) | ||
| { | ||
| p_qtd->buffer[i] |= (uint32_t) info->ptr_wrap + 4096 * page; | ||
| } |
There was a problem hiding this comment.
I don't quite understand these lines, are you trying to queue both linear and wrap buffer into one TD ? Which I don't think is possible, we probably need 2 TDs for this.
There was a problem hiding this comment.
Yes I'm trying to queue both parts in 5*4kB TDs. Fifo need to be 4k aligned and has a size of multiple of 4K, for a max of 20K.
TD[0] can start at a arbitrary address and TD[1]-TD[4] must start at 4k boundary.
Take an example of a 8k fifo filled between 2000-100:

TD[0] is set to offset of fifo->ptr_lin, then each TD is aligned to 4k until len_lin is finished.
Then it wrap to top and start at offset 0.
There was a problem hiding this comment.
I think you mis-read the TD specs, within this function, it only preps 1 TD. The buffer[] page array is only used when the total bytes is large enough and memory cross the 4k boundary e.g when total bytes is 20 KB.
There was a problem hiding this comment.
within this function, it only preps 1 TD
You're right.
In fact I mean 5 pointers within the same TD, sorry for the confusion.

we probably need 2 TDs for this.
I've tried 2 TDs, one for linear and one for wrapped part. In this case it cut the data into 2 separate transfers, for example cdc will receive half data.
There was a problem hiding this comment.
we can transfer 1 TD after another instead of using 2 TDs at once. Can you update the above code to initialize the buffer page correctly. It should only affected by ptr_lin, and is mostly identical to existing qtd_init(). In fact, I think we should just use the qtd_init(ptr_lin, len) instead of having additional qtd_init_fifo()
There was a problem hiding this comment.
the requirement with 4K aligned is too specific to make its way into the buffer page array set up. And this does not work with other MCU dcd.
Yes it is specific, so I've introduced a on/off switch in #1063 to not enable fifo_xfer by default, except explicitly.
For ISO, you have to understand this limit and need to declare the fifo depth to be multiple of ISO frame.
That's won't work since sample length could be +-1, wrapped part has to be always considered.
There was a problem hiding this comment.
Yes it is specific, so I've introduced a on/off switch in #1063 to not enable fifo_xfer by default, except explicitly.
I don't like the TUD_AUDIO_PREFER_RING_BUFFER, it is only temporarily solution, we will eventual remove that.
That's won't work since sample length could be +-1, wrapped part has to be always considered.
Apparently, I am not aware of this issue. In this case, can you modify to make it more generic. xfer_fifo() will make use of qtd_init() with the linear part first. Then update the buffer pagep[] with wrapped part if following conditions is met
- Linear len < total _bytes
- wrap pointer is 4k alignment.
There was a problem hiding this comment.
Then update the buffer pagep[] with wrapped
you mean modify buffer pagep[] inside xfer_fifo() and remove qtd_init_fifo() ?
There was a problem hiding this comment.
it is mostly to reduce code duplication, for now, just keep it as it is if it is too confused. Only set up the buffer page only above 2 condition are met. currently wrapped part is always set up.
There was a problem hiding this comment.
@HiFiPhile to clarify: not all edpt_xfer_fifo() need to combine linear + wrapped part, e.g CDC should have no issue breaking these into 2 sub transfers (one after another when USB complete ISR). Therefore not all fifo buffer need to be 4K. It is mostly for ISO applcation/driver, so having a 4K check would fit both.
| //------------- Prepare qtd -------------// | ||
|
|
||
| // In case of : wrapped part is present & buffer is aligned to 4k & buffer size is multiple of 4k | ||
| if (total_bytes > fifo_info.len_lin && (uint32_t)fifo_info.ptr_wrap == tu_align4k((uint32_t)fifo_info.ptr_wrap) && tu_fifo_depth(ff) == tu_align4k(tu_fifo_depth(ff))) |
There was a problem hiding this comment.
I've add the switch, should be good but haven't tested. (better to have a macro bool is_aligned_4k(x))
There was a problem hiding this comment.
yeah, the condition look good, you can use the !tu_offset4k() as is_aligned_4k(), which make it easier to read.
|
@HiFiPhile I am doing resolving conflict and refactor this pr just now. Please hold on a bit if you plan to work more on this |
cc454bb to
9bed4e2
Compare
hathach
left a comment
There was a problem hiding this comment.
Thank you for your effort adding the xfer_fifo. I am happy with the refactored code now, please verify if it works with your ISO setup. Once it is confirmed, we could merge it and resolve other case (total > len and buffer is not 4k aligned) later on when needed.
|
Now UAC2 is broken with no transfer, maybe forget to reset EP busy flag in But I don't remember busy was set to false before... |
|
@HiFiPhile which audio example you are running |
I've tested both Somehow EP flags are not reset when closed. With xfer_fifo enabled it fails for the same reason: Could be fixed by adding: |
|
@HiFiPhile yeah, I think this is the right fix, closing endpoint should also reset its state. Please make the commit if possible void usbd_edpt_close(uint8_t rhport, uint8_t ep_addr)
{
TU_ASSERT(dcd_edpt_close, /**/);
TU_LOG2(" CLOSING Endpoint: 0x%02X\r\n", ep_addr);
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
dcd_edpt_close(rhport, ep_addr);
+ _usbd_dev.ep_status[epnum][dir].stalled = false;
+ _usbd_dev.ep_status[epnum][dir].busy = false;
+ _usbd_dev.ep_status[epnum][dir].claimed = false;
return;
} |
|
@HiFiPhile let me know if the rest of your testing is going well enough |
|
It goes well in my side, you can merge it. |
great, thank you very much for the PR and testing |
Describe the PR
1st part of #926.