2020-08-05 04:00 AM
My Ethernet driver is not wrapping as I expect.
Section "61.10.1 Descriptor Overview" in RM0399 states that descriptors up to N-1 is owned by the DMA and the DMA continues to process descriptors until the Current Descriptor Pointer == Tail Pointer.
In order to exit suspend state, the tail pointer must be updated so that the Current Descriptor Pointer < Tail Pointer.
Using the example in Figure 841, the tail pointer points to entry 10 (which is not a valid entry since only 0 to 9 are valid). I can see that the DMA runs until the current descriptor points to 10, but it does not wrap back to zero. If the tail pointer must be larger than the current pointer, what should it be? Should it point to entry 11??
When will the DMA wrap, and start operating on buffer 0 again?
Solved! Go to Solution.
2022-01-15 05:41 PM
The following error report is for all reference manuals of H7 with ETH peripheral:
According to the information from others and common sense, the following bold formatted sentences in the respective sections are wrong and misleading:
---------
The Channel Tx descriptor tail pointer register (ETH_DMACTXDTPR) or Channel Rx descriptor tail pointer register (ETH_DMACRXDTPR) contains the pointer to the descriptor address (N). The base address and the current descriptor pointer decide the address of the current descriptor that the DMA can process. The descriptors up to one location less than the one indicated by the descriptor tail pointer (N – 1) are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs:
Current Descriptor Pointer == Descriptor Tail Pointer;
The DMA enters the Suspend state when this condition occurs. The application must perform a write operation to the Descriptor tail pointer register and update the tail pointer so that the following condition is met:
Current Descriptor Pointer < Descriptor Tail Pointer;
---------
Descriptor tail pointer registers doesn't somehow magically "contain" some values and address of the descriptor N is not the best value for initialization also. Typically the best will be N+1 or anything that effectively disables stopping on tail pointer match. It is safe because even, if the DMA will fill all of the descriptors before those are processed by application and wrap around, it will still enter the suspended state, because the OWN bit on the descriptor 0 will still be cleared. Therefore the tail pointer does not determine the ownership of descriptors and the text is misleading. And relational operator "<" is not the logical opposite of "==". The "!=" is, which includes also the ">" case. Common sense and point 4 in Alister's detailed comment above tells that hardware just stops processing descriptors, if the tail pointer equals current descriptor address, and doesn't do "less than" comparison, because otherwise the feature would be practically useless.
And there is another tail pointer related misinformation in register descriptions:
---------
Channel Tx descriptor tail pointer register (ETH_DMACTXDTPR)
The ChannelTx Descriptor Tail Pointer register points to an offset from the base and indicates the location of the last valid descriptor.
Channel Rx descriptor tail pointer register (ETH_DMACRXDTPR)
The Channel Rx Descriptor Tail Pointer Points to an offset from the base and indicates the location of the last valid descriptor.
---------
Besides the missing space in "ChannelTx", missing word "register" for Rx and an unnecessary capital letter in "Points", the information says those registers hold the offset from the descriptor list base address. Again an information from others and even the HAL ETH driver on the contrary shows that those registers hold the absolute address of the tail pointer.
And one more thing. Contrary to the reference manuals, CMSIS header files name ETH registers (not only these two) without the "X" letter (formatted as bold in the above example) in the names. One or the other must be corrected.
Other topics confirming the presented information:
https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet
https://community.st.com/s/question/0D50X0000AU4PuySQF/ethernet-receive-stability-using-tcp
@Imen DAHMEN, this information should be confirmed and the reference manuals corrected.
2020-08-05 04:45 AM
As I know Ethernet well, but haven't worked on H7, I could be wrong, but from a quick look the whole page 3036 looks terribly misleading. It seems to describe not how a DMA hardware works, but how some limited mind thinks a driver should be implemented. And it seems that the ST's non-working H7 ETH HAL driver is implemented exactly like that... @alister, can you comment on this?
Meanwhile read alister's report:
https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet
And take a look on other related issues:
2020-08-05 05:29 AM
I agree, it does not seem to describe the DMA itself and implementing it as such does not work. Some issues I find:
I have an in-house IP stack that I've ported to new hardware based on STM32H7 and is trying to write driver that plugs in to our IP stack. Never have I struggled this much getting Ethernet driver going and given my points above, I am totally confused as to what to do. I am in total trail-and-error mode which is not how this should work.
2020-08-06 04:48 AM
>The Descriptor ring length register (ETH_DMACRXRLR) must hod the number of descriptors
It should be configured 1 less than your number of descriptors.
>I cannot figure out the purpose of the tail pointer
Refer some notes below.
>I will set-up a TX buffer, but it will not get transmitted until the second buffer gets written
Could only guess. Each descriptor may link two buffers. I suggest read the working driver at https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet.
General DMA descriptor notes
2020-08-06 08:06 AM
Thanks, that helped a lot. Knowing what is right and what is not eliminated enough issues that I could get my driver going. Thanks also for your bug-fix in the ST driver. That, with your documentation was very useful.
My TX error turned out to be something else: I still have cache disabled (always start that way to get things going) but if I write the OWN bit in the TX descriptor, and then the tail pointer register to get DMA going, it would not see the change to the OWN bit yet. I had to add a memory barrier there to resolve my TX issue.
This makes sense since the ARM can do out-of-order writes with cache on or off.
2020-08-06 03:36 PM
The cache cleaning and barrier for the descriptors could never out-perform using MPU region(s) for them.
2022-01-15 05:41 PM
The following error report is for all reference manuals of H7 with ETH peripheral:
According to the information from others and common sense, the following bold formatted sentences in the respective sections are wrong and misleading:
---------
The Channel Tx descriptor tail pointer register (ETH_DMACTXDTPR) or Channel Rx descriptor tail pointer register (ETH_DMACRXDTPR) contains the pointer to the descriptor address (N). The base address and the current descriptor pointer decide the address of the current descriptor that the DMA can process. The descriptors up to one location less than the one indicated by the descriptor tail pointer (N – 1) are owned by the DMA. The DMA continues to process the descriptors until the following condition occurs:
Current Descriptor Pointer == Descriptor Tail Pointer;
The DMA enters the Suspend state when this condition occurs. The application must perform a write operation to the Descriptor tail pointer register and update the tail pointer so that the following condition is met:
Current Descriptor Pointer < Descriptor Tail Pointer;
---------
Descriptor tail pointer registers doesn't somehow magically "contain" some values and address of the descriptor N is not the best value for initialization also. Typically the best will be N+1 or anything that effectively disables stopping on tail pointer match. It is safe because even, if the DMA will fill all of the descriptors before those are processed by application and wrap around, it will still enter the suspended state, because the OWN bit on the descriptor 0 will still be cleared. Therefore the tail pointer does not determine the ownership of descriptors and the text is misleading. And relational operator "<" is not the logical opposite of "==". The "!=" is, which includes also the ">" case. Common sense and point 4 in Alister's detailed comment above tells that hardware just stops processing descriptors, if the tail pointer equals current descriptor address, and doesn't do "less than" comparison, because otherwise the feature would be practically useless.
And there is another tail pointer related misinformation in register descriptions:
---------
Channel Tx descriptor tail pointer register (ETH_DMACTXDTPR)
The ChannelTx Descriptor Tail Pointer register points to an offset from the base and indicates the location of the last valid descriptor.
Channel Rx descriptor tail pointer register (ETH_DMACRXDTPR)
The Channel Rx Descriptor Tail Pointer Points to an offset from the base and indicates the location of the last valid descriptor.
---------
Besides the missing space in "ChannelTx", missing word "register" for Rx and an unnecessary capital letter in "Points", the information says those registers hold the offset from the descriptor list base address. Again an information from others and even the HAL ETH driver on the contrary shows that those registers hold the absolute address of the tail pointer.
And one more thing. Contrary to the reference manuals, CMSIS header files name ETH registers (not only these two) without the "X" letter (formatted as bold in the above example) in the names. One or the other must be corrected.
Other topics confirming the presented information:
https://community.st.com/s/question/0D50X0000C6eNNSSQ2/bug-fixes-stm32h7-ethernet
https://community.st.com/s/question/0D50X0000AU4PuySQF/ethernet-receive-stability-using-tcp
@Imen DAHMEN, this information should be confirmed and the reference manuals corrected.
2022-01-19 05:55 AM
Hello @Piranha ,
Thank you for pointing out the errors.
I escalated your feedback internally for review and correction.
Thanks
Imen
2022-01-19 11:28 AM
@Imen DAHMEN ,
Thank you for the care.
By this occasion, could you check another point?
It seems that addresses of RX buffers must be aligned on 512 bytes.
In my testing, lesser alignment (on 32 bytes for example) caused errors in RX data.
The RM does not mention this.
Also, the description text on BUF1AP, BUF2AP in RX descriptors has something about LS bits, shifts, offsets that looks confusing. RM0433 tables 540,542 on pg. 2866
Thanks,
-- pavel
2022-01-19 11:37 PM
Hi Pavel,
Thank you for confirming.
@Imen DAHMEN , thank you for following up and looking at correcting in documentation.