DMA: HDMA init/run must interrupt/cancel regular DMA
This commit is contained in:
parent
f0ce0f63af
commit
2cecde26fb
2 changed files with 20 additions and 2 deletions
|
@ -30,17 +30,21 @@ void DmaController::RunSingleTransfer(DmaChannelConfig &channel)
|
||||||
channel.TransferSize--;
|
channel.TransferSize--;
|
||||||
transferByteCount--;
|
transferByteCount--;
|
||||||
i++;
|
i++;
|
||||||
} while(channel.TransferSize > 0 && transferByteCount > 0);
|
} while(channel.TransferSize > 0 && transferByteCount > 0 && !channel.InterruptedByHdma);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DmaController::RunDma(DmaChannelConfig &channel)
|
void DmaController::RunDma(DmaChannelConfig &channel)
|
||||||
{
|
{
|
||||||
|
if(channel.InterruptedByHdma) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
//Manual DMA transfers run to the end of the transfer when started
|
//Manual DMA transfers run to the end of the transfer when started
|
||||||
RunSingleTransfer(channel);
|
RunSingleTransfer(channel);
|
||||||
|
|
||||||
//TODO : Run HDMA when needed, between 2 DMA transfers
|
//TODO : Run HDMA when needed, between 2 DMA transfers
|
||||||
} while(channel.TransferSize > 0);
|
} while(channel.TransferSize > 0 && !channel.InterruptedByHdma);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DmaController::InitHdmaChannels()
|
void DmaController::InitHdmaChannels()
|
||||||
|
@ -57,6 +61,7 @@ void DmaController::InitHdmaChannels()
|
||||||
if(_hdmaChannels & (1 << i)) {
|
if(_hdmaChannels & (1 << i)) {
|
||||||
//"1. Copy AAddress into Address."
|
//"1. Copy AAddress into Address."
|
||||||
ch.HdmaTableAddress = ch.SrcAddress;
|
ch.HdmaTableAddress = ch.SrcAddress;
|
||||||
|
ch.InterruptedByHdma = true;
|
||||||
|
|
||||||
//"2. Load $43xA (Line Counter and Repeat) from the table. I believe $00 will terminate this channel immediately."
|
//"2. Load $43xA (Line Counter and Repeat) from the table. I believe $00 will terminate this channel immediately."
|
||||||
ch.HdmaLineCounterAndRepeat = _memoryManager->ReadDma((ch.SrcBank << 16) | ch.HdmaTableAddress);
|
ch.HdmaLineCounterAndRepeat = _memoryManager->ReadDma((ch.SrcBank << 16) | ch.HdmaTableAddress);
|
||||||
|
@ -89,6 +94,8 @@ void DmaController::RunHdmaTransfer(DmaChannelConfig &channel)
|
||||||
const uint8_t *transferOffsets = _transferOffset[channel.TransferMode];
|
const uint8_t *transferOffsets = _transferOffset[channel.TransferMode];
|
||||||
uint8_t transferByteCount = _transferByteCount[channel.TransferMode];
|
uint8_t transferByteCount = _transferByteCount[channel.TransferMode];
|
||||||
|
|
||||||
|
channel.InterruptedByHdma = true;
|
||||||
|
|
||||||
uint32_t srcAddress;
|
uint32_t srcAddress;
|
||||||
if(channel.HdmaIndirectAddressing) {
|
if(channel.HdmaIndirectAddressing) {
|
||||||
srcAddress = (channel.HdmaBank << 16) | channel.TransferSize;
|
srcAddress = (channel.HdmaBank << 16) | channel.TransferSize;
|
||||||
|
@ -125,6 +132,12 @@ void DmaController::ProcessHdmaChannels()
|
||||||
if(_hdmaChannels) {
|
if(_hdmaChannels) {
|
||||||
_hdmaPending = true;
|
_hdmaPending = true;
|
||||||
|
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
if(_hdmaChannels & (1 << i)) {
|
||||||
|
_channel[i].InterruptedByHdma = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
DmaChannelConfig &ch = _channel[i];
|
DmaChannelConfig &ch = _channel[i];
|
||||||
if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) {
|
if((_hdmaChannels & (1 << i)) == 0 || ch.HdmaFinished) {
|
||||||
|
@ -198,6 +211,10 @@ void DmaController::Write(uint16_t addr, uint8_t value)
|
||||||
|
|
||||||
//"and an extra 8 master cycles overhead for the whole thing"
|
//"and an extra 8 master cycles overhead for the whole thing"
|
||||||
_memoryManager->IncrementMasterClockValue<8>();
|
_memoryManager->IncrementMasterClockValue<8>();
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
_channel[i].InterruptedByHdma = false;
|
||||||
|
}
|
||||||
|
|
||||||
for(int i = 0; i < 8; i++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
if(value & (1 << i)) {
|
if(value & (1 << i)) {
|
||||||
//"Then perform the DMA: 8 master cycles overhead and 8 master cycles per byte per channel"
|
//"Then perform the DMA: 8 master cycles overhead and 8 master cycles per byte per channel"
|
||||||
|
|
|
@ -24,6 +24,7 @@ struct DmaChannelConfig
|
||||||
bool DoTransfer;
|
bool DoTransfer;
|
||||||
bool HdmaFinished;
|
bool HdmaFinished;
|
||||||
|
|
||||||
|
bool InterruptedByHdma;
|
||||||
bool UnusedFlag;
|
bool UnusedFlag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue