USB driver development based on DWC2 - starting and stopping S/G DMA mode - EPENA state BNA and XFER COMPLETE interrupt
1.
Introduction
DWC2
supports
S/G DMA
, namely
Scatter/Gather DMA
mode
,
which
can
free up
the CPU
to achieve efficient data flow.
Of course, the IP
configuration
needs
to support this mode.
When
bit32
of
register
GHWCFG4
is
1
, it means that the current
IP
configuration supports this
DMA
mode.
When the IP
supports this mode, the user can also configure whether to enable this mode.
In device mode, the software configures
bit 23
of the
DCFG
register
to
1
to enable the
DMA
mode. Of course,
the DMA
mode
must be enabled at this time
, that is,
DMAEn
of the
GAHBCFG
register
is configured to
1.
If it is
HOST
mode, configure
bit 23
of
HCFG
.
2.
Start and stop
S/G DMA
The original intention of S/G DMA
is to use the descriptor linked list
for
the interaction between
hardware
DMA
and software to achieve uninterrupted streaming processing
.
Users only need to prepare descriptors. When the high-speed hardware descriptors are ready, they can start processing. The rest is
handled
by the hardware
S/G DMA
. The hardware
DMA
continuously scans the descriptors to carry out the corresponding data transfer. After the transfer is completed, an interrupt is generated, and the processing can be stopped or not and then returned to the descriptor linked list to continue processing. The cooperation of hardware and software can achieve
uninterrupted streaming processing
in a ring
.
This method is naturally suitable for
ISOC
transmission, which is a streaming and uninterrupted transmission. Therefore, for
ISOC
,
S/G DMA
does not stop automatically
(
unless an error occurs or the descriptor is not ready
)
. For
non-isochronous transmission such as
BULK
, it stops automatically after processing a descriptor list
(L=1)
. Of course, there is also a trick to configure the descriptor's
MTRF=1
to indicate that streaming processing is required. At this time,
it does not stop when encountering a descriptor
with
L=1
, but
continues to process like
ISOC
.
Simply put,
ISOC
transmission will continuously loop through the descriptor list, while
BULK
and
INT
non-isochronous transmissions require the descriptor
MTRF=1
to indicate continuous looping of the descriptor list, otherwise it will
stop when
L=1
is encountered
.
The start
of
S/G DMA
is
set by
EPENA
in
bit31
of the
DIEP
and
DOEP
control registers
. The software sets this bit to
1
to start
S/G DMA
processing. Before this, the descriptor and
DIEPDMAi/DOEPDMAi
information need to be set.
The hardware
S/G DMA
starts processing the descriptor when
it detects that
EPENA
is
1
, and then
clears
EPENA
according to the specific stop condition
(
processing is completed or an error occurs or the descriptor is not ready
)
. Of course, the software can also
actively set
EPENA
to
0
to stop
DMA
work
before
EPENA
has been set but not cleared by hardware.
Here is a brief summary
Assuming that the user only prepares one descriptor and sets
L=1
,
IOC=1
, after the hardware processes this descriptor, does it actively stop
DMA
and generate
a BNA (
descriptor not ready
)
interrupt?
If the current descriptor is actively stopped after completion, only
an XFER COMPLETE
interrupt will be generated without
a BNA
interrupt.
If you do not actively stop and continue to circle back to query the descriptor,
a BNA
will be generated because the descriptor is not ready, and
DMA
will be forced to stop at this time
.
|
|
XFER COMPLETE
INTERRUPTION
|
BNA
interruption
|
|
MTRF=0
|
INT/BULK OUT
|
produce
|
No
|
INT
interrupt transmission is exactly the same as
BULK
transmission
|
INT/BULK IN
|
produce
|
No
|
||
ISOC IN
|
produce
|
produce
|
ISOC
does not stop automatically
whether it is
IN
or
OUT,
and
will only stop
when BNA
is generated
.
BULK
will stop automatically
whether it is
IN
or
OUT,
and
will not generate
BNA
.
|
|
ISOC OUT
|
produce
|
produce
|
||
MTRF=1
|
INT/BULK OUT
|
produce
|
produce
|
When
L=1
is encountered
, it will go back to the start descriptor to continue processing. Once all descriptors are set, they must be set.
|
INT/BULK IN
|
/
|
/
|
No such configuration
|
|
ISOC IN
|
/
|
/
|
ISOC
and control transmission do not have this configuration
|
|
ISOC OUT
|
/
|
/
|
ISOC
and control transmission do not have this configuration
|
For details, please refer to the flowchart in the programming guide
INT/BULK IN
is shown in the figure below.
The start is when
EPENA
is set, and the stop is when
the descriptor with
L=1
is encountered. Of course, the descriptor will stop if
BNA
or other errors are generated when it is not ready. So it will stop actively when
L=1
is encountered
.
INT/BULK OUT
is shown in the figure below
Startup is when
EPENA
is set and
there is data in
RXFIFO
, and stop is when encountering
a descriptor with
L=1
. Of course, it will also stop if the descriptor is not ready and
BNA
or other errors occur. So it will automatically stop when encountering
L=1
.
The stop condition shown in the figure below should be wrong, it should be drawn as
ISOC OUT
,
BULK OUT
When
MTRF=0
and
L=1
is encountered
, it will stop automatically.
When
MTRF=1
, it will continue to wrap around to the beginning of the descriptor to continue processing.
ISOC IN
When starting
,
EPENA
is
set. When
L=1
is encountered,
it does not stop actively but goes back to the start descriptor to continue processing. Of course, it will also stop if the descriptor is not ready and
BNA
or other errors are generated.
ISOC OUT
When starting,
EPENA
is set and
there is data in
RXFIFO
. When
L=1
is encountered,
it does not stop actively but goes back to the start descriptor to continue processing. Of course, it will also stop if the descriptor is not ready and
BNA
or other errors are generated.
3.
Actual
measurement
The following tests are performed for
various situations where
MTRF=0
ISOC IN
The following information is printed in the
In
interrupt
Print the following information when ready to send
You can see the print information as follows
set itf 4 1
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:281
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:281
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:281
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:201
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
mic set samp:16000
inep2,int:201
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:2291
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:2291
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:2291
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
inep2,int:2291
inep2,xfer,ctrl:8480c0
inep2,bna,DMA=28182f08 8480c0
Print first and prepare to receive
inep2 buf:281977ac tosnd 32 dma:28182f00 abff020 281977ac
Re-printing enters interrupt
inep2,int:201
Printing again and entering
the complete
interrupt
inep2,xfer,ctrl:8480c0
and
BNA
interrupt
inep2,bna,DMA=28182f08 8480c0
Here we can see that the control register is printed
8480c0
, that is,
EPENA=0
.
Theoretically,
when the
complete
interrupt
is generated,
DMA
has not stopped yet
and EPENA=1
.
When
the BNA
interrupt
is generated
,
DMA
stops and
EPENA=0
. However,
the BNA
and
complete
interrupts are generated at the same time, so EPENA=0 is seen here
.
ISOC OUT
Print when ready to receive
Print in
out
interrupt
The print information is as follows
set itf 3 1
outep2 buf:28197914 torcv 32 dma:28182f78 e000020 28197914
sp set samp:32000
outep2,int:1
outep2,xfer,ctrl:800480c0
outep2,int:200
outep2,bna,DMA=28182f80 480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
outep2,int:2001
outep2,xfer,ctrl:800480c0
outep2,int:200
outep2,bna,DMA=28182f80 480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
Print first and prepare to send
outep2 buf:28197914 torcv 32 dma:28182f78 e000020 28197914
Then print again and enter interrupt
outep2,int:1
Printing again is
complete
interrupt.
At this time, we see that the control register is
800480c0
,
EPENA=1
, that is,
DMA
is not stopped.
Later, the host receives
OUT
data. At this time, since the software has not prepared the descriptor,
a BNA
interrupt
is generated.
Print
outep2,int:200
outep2,bna,DMA=28182f80 480c0
That is
, there are
xfer complete
interrupts
and
BNA
interrupts.
The current
OUT
can be received normally and only
the complete
interrupt is triggered. After a while, the host continues
OUT
. At this time, if there is no ready descriptor,
BNA
will be generated
and
DMA
will be stopped
.
BULK OUT
Print when ready to receive
Print in
out
interrupt
The print information is as follows
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:b8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
outep2,int:1
outep2,xfer,ctrl:a8200
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
You can see that the first print
outep2 buf:28307040 torcv 1536 dma:28307c40 a000600 28307040
Re-print interrupt
outep2,int:1
Then print
the xfer complete
interrupt.
At this time, the control register is
a8200
, that is,
DMA
stops
EPENA=0.
outep2,xfer,ctrl:b8200
That is, there is only
xfer complete
interrupt
,
no
BNA
interrupt, because
DMA
stops automatically.
BULK IN
The following information is printed in the
In
interrupt
Print the following information when ready to send
The print information is as follows
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:888200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
inep2,int:2091
inep2,xfer,ctrl:898200
Print first and prepare to send
inep2 buf:2830600c tosnd 5 dma:28307030 a000005 2830600c
Then print into interrupt
inep2,int:2091
Print xfer complete
interrupt
again
inep2,xfer,ctrl:898200
That is, there is only
xfer complete
interrupt
,
no
BNA
interrupt, because
DMA
stops automatically.
4.
Things
to note
4.1
Clearing the interrupt timing issue
To clear the interrupt, you must clear it immediately after reading the interrupt, because there may be new interrupts when the interrupt service function is processing. If you clear it after the interrupt function, the newly generated interrupt will be cleared.
set itf 4 1
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38
A total of 7
transactions
were sent
, and the second transaction did not generate
an
XFERCOMPL
interrupt.
The 7th
transaction
no longer generates
XFERCOMPL
and
BNA
interrupts.
At this time, no data was captured on the bus.
set itf 4 1
inep2 buf:281977fc tosnd 64 dma:28182f38 abff040 281977fc
inep2,int
inep2,xfer,ctrl:848180
inep2,bna,DMA=28182f40 848180
inep2 done
inep2 buf:281977fc tosnd 64 dma:28182f38 abff040 281977fc
The register value at this time
is
0x03000940
00848180 00000000 00000080 00000000 0007ff80 28182f40 00000040 2819783c 00000000 00000000 00000080 00000000
Change to
4.2 ISOC OUT
and
IOSC IN
BNA
timing
is different
ISOC IN and OUT
generate
BNA at different times
For
IN, once the previous descriptor is processed
, as long as there is space in TXFIFO,
the next descriptor
will be processed immediately.
If the next descriptor is not ready at this time, BNA will be generated immediately,
so
complete and bna are generated at the same time.
As for
OUT
,
after
the previous
descriptor
is processed,
DMA
needs to
wait for
data to be received in
RXFIFO before
it can process the next
descriptor
.
If the next descriptor
is not ready,
BNA will be generated. Therefore
, after
completion,
BNA
will be generated only
after the next data is received
.
4.3
Location of DMA settings
DMA[0]
should be set last because if
DMA
is not stopped, when the software updates the descriptor, the hardware needs to read
the status of
DMA[0]
to allow
DMA
access before accessing it. Therefore, the software must prepare all the information before configuring
this part of
DMA[0]
to ensure that when the hardware can access the descriptor, other information is ready.
set itf 3 1
outep2 buf:28197914 torcv 32 dma:28182f78 e000020 28197914
sp set samp:32000
outep2,int:1
outep2,xfer,ctrl:800480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
outep2,int:1
outep2,xfer,ctrl:800480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
outep2,int:1
outep2,xfer,ctrl:800480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
outep2,int:211
outep2,xfer,ctrl:800480c0
outep2,bna,DMA=28182f80 800480c0
outep2 buf:28197914 torcv 64 dma:28182f78 e000040 28197914
Int:211
indicates that
BNA
has
caused
DMA
to stop, that is,
EPENA=0
. A new
OUT
has arrived, and
EPENA=0
at this time
, so
an
OUTTknEPdis
event is generated.
5.
Conclusion
When using
S/G DMA
mode, you need to pay attention to
the start and stop conditions of
DMA
.
ISOC
hardware will not stop actively, so if the next descriptor is not prepared in time, it will cause
BNA
interrupts and need to be properly handled. Non-
ISOC
hardware will automatically stop when encountering
L=1
descriptor, so the software can have enough time to prepare the next descriptor and restart.
There are differences in the timing of BNA
generation
for
ISOC IN
and
OUT
,
as explained in the text.
The timing of clearing interrupts during interrupts and
the location of
DMA[0]
settings are also things that need attention.
The above mainly clarifies
the start and stop of
S/G DMA
and some points that need attention. How to actually use
S/G DMA
to achieve efficient and uninterrupted streaming transmission is a very important content, which I will share later when I have time.