186
Rabbit 4000 Microprocessor User’s Manual
When all these conditions occur, the DMA will overwrite the next-to-last byte in the transmit
FIFO, and that particular byte will never be transmitted.
There are several ways to avoid this bug.
Always mark the buffer that contains the end-of-frame byte as the final buffer, and restart the DMA
once that buffer has been transmitted.
Make sure that the DMA will not return to this channel before the transmitter has sent one byte
from the transmit FIFO.
Place the end-of-frame byte in a separate DMA buffer.
The Ethernet driver provided by Rabbit Semiconductor in Dynamic C is written so that
this bug never occurs.
19.3.8 DMA/Block Copy Interaction
When a DMA transfer occurs during a block copy instruction (LDIR, LDDR, COPY,
COPYR, UMA, or UMS) while executing code out of 16-bit memory with the “advanced
16-bit mode” enabled, the code prefetch queue and program counter will become out-of-
synch. This means that one or two incorrect bytes (depending on the 16-bit alignment of
the instruction) are reloaded and presented to the processor as instructions when execution
is “rewound” after the DMA transfer. The result of this mismatch is that the block copy
instruction does not complete.
The only way to prevent this from occurring is to prevent DMA transfers during block
copy instructions, either by disabling the DMA or by increasing the processor priority
above the priority of the DMA transfer.
There is a workaround. The processor’s BC register is used as a program counter by the
block copy instructions, and will be nonzero if the block copy instruction did not com-
plete. By checking the value of BC and jumping back to the block copy instruction if it is
nonzero, the block copy instruction is restarted with all the current register values (source
and destination pointers) and will continue where it left off. Rabbit Semiconductor’s
Dynamic C compiler automatically includes this wrapper code whenever it identifies a
block copy instruction.
19.3.9 Single-Byte DMA Requests to internal I/O Registers
When timed or external DMA requests are enabled and set to transfer a single byte at a
time to an internal I/O register, two bytes will actually be transferred. The simplest
workaround is to double each data byte in the buffer; two bytes will be transmitted, but
they will be identical, so the actual I/O register setting will not change.