gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

DS development > dma interrupts

#174057 - coreyh2 - Sun May 16, 2010 5:05 am

I was trying to see if dma interrupts worked. I have some code that doesn't produce the results I expect. The dma interrupts never seem to go off. It doesn't seem to crash as the variable change from the VblankHandler works.

This code is just a test. I know the multiple dmaCopyHalfWordsAsynch won't actually work asynchronously. I have some more tests planned to see how fast different copies are.

http://tank.windwireless.net/~crsntlvs/admatests01.7z

Code:

/* CHH */

#include <nds.h>
#include <stdlib.h>
#include "chhprint.h"
 

DTCM_DATA unsigned int frame_count = 0;

/*
DTCM_DATA char* DMA00_string01;
DTCM_DATA char* DMA00_string02;

DTCM_DATA char* DMA01_string01;
DTCM_DATA char* DMA01_string02;

DTCM_DATA char* DMA02_string01;
DTCM_DATA char* DMA02_string02;

DTCM_DATA char* DMA03_string01;
DTCM_DATA char* DMA03_string02;
*/
//ITCM_CODE void VblankHandler();

void VblankHandler();
void dma00Handler();
void dma01Handler();
void dma02Handler();
void dma03Handler();

int main(void)
{
   
   int frame_index = 0;
   int ContineUpdating = true;
   const int d_buffersize = 128;

   char* DMA00_string01;
   char* DMA00_string02;

   char* DMA01_string01;
   char* DMA01_string02;

   char* DMA02_string01;
   char* DMA02_string02;

   char* DMA03_string01;
   char* DMA03_string02;

   chhprintinit();

   /*
   DMA00_string01 = memalign(32, sizeof(char) * d_buffersize);
   DMA00_string02 = memalign(32, sizeof(char) * d_buffersize);
   DMA01_string01 = memalign(32, sizeof(char) * d_buffersize);
   DMA01_string02 = memalign(32, sizeof(char) * d_buffersize);
   DMA02_string01 = memalign(32, sizeof(char) * d_buffersize);
   DMA02_string02 = memalign(32, sizeof(char) * d_buffersize);
   DMA03_string01 = memalign(32, sizeof(char) * d_buffersize);
   DMA03_string02 = memalign(32, sizeof(char) * d_buffersize);
   */

   DMA00_string01 = malloc(sizeof(char) * d_buffersize);
   DMA00_string02 = malloc(sizeof(char) * d_buffersize);
   DMA01_string01 = malloc(sizeof(char) * d_buffersize);
   DMA01_string02 = malloc(sizeof(char) * d_buffersize);
   DMA02_string01 = malloc(sizeof(char) * d_buffersize);
   DMA02_string02 = malloc(sizeof(char) * d_buffersize);
   DMA03_string01 = malloc(sizeof(char) * d_buffersize);
   DMA03_string02 = malloc(sizeof(char) * d_buffersize);

   irqEnable(IRQ_DMA0 | IRQ_DMA1 | IRQ_DMA2 | IRQ_DMA3);

//   irqSet(IRQ_VBLANK, (void(*)())VblankHandler);

   irqSet(IRQ_VBLANK, VblankHandler);
   irqSet(IRQ_DMA0, dma00Handler);
   irqSet(IRQ_DMA1, dma01Handler);
   irqSet(IRQ_DMA2, dma02Handler);
   irqSet(IRQ_DMA3, dma03Handler);
   
   DC_FlushAll();
   dmaCopyHalfWordsAsynch(0, DMA00_string01, DMA00_string02, d_buffersize);   
   dmaCopyHalfWordsAsynch(1, DMA01_string01, DMA01_string02, d_buffersize);   
   dmaCopyHalfWordsAsynch(2, DMA02_string01, DMA02_string02, d_buffersize);   
   dmaCopyHalfWordsAsynch(3, DMA03_string01, DMA03_string02, d_buffersize);   

   while(1)
   {
      swiWaitForVBlank();
      if(ContineUpdating)
      {
           if((frame_index % 60) == 0)
         {
              chhprintf(chh_TOP_SCREEN, "%d\n", frame_count);
         }
         if(frame_index >= (60 * 20)) ContineUpdating = false;
         frame_index++;
      }
   }   
   return 0;
}

//ITCM_CODE void VblankHandler()


void VblankHandler()
{
   frame_count++;
}

void dma00Handler()
{
   chhprintf(chh_BOTTOM_SCREEN, "dma00 done\n");
}
void dma01Handler()
{
   chhprintf(chh_BOTTOM_SCREEN, "dma01 done\n");
}
void dma02Handler()
{
   chhprintf(chh_BOTTOM_SCREEN, "dma02 done\n");
}
void dma03Handler()
{
   chhprintf(chh_BOTTOM_SCREEN, "dma03 done\n");
}

_________________
Deadening 2

#174058 - Cearn - Sun May 16, 2010 8:43 am

Enabling IRQs requires two toggles: one for the sender (in this case DMA) and one for the receiver (the IRQ system). irqSet() and irqEnable() sets the receiver bits, but only the sender bits for REG_DISPSTAT. You need to add DMA_IRQ_REQ to the DMA flags. See also gbatek:dma (but note that libnds uses one 32bit REG_DMAnCNT, whereas GBATek splits it in two 16bit ones).

#174060 - coreyh2 - Sun May 16, 2010 11:40 am

thanks.

Code:

static inline void dmaCopyHalfWordsAsynch_IRQ(uint8 channel, const void* src, void* dest,
                                   uint32 size)
{
   DMA_SRC(channel) = (uint32)src;
   DMA_DEST(channel) = (uint32)dest;
   DMA_CR(channel) = DMA_COPY_HALFWORDS | DMA_IRQ_REQ | (size>>1);
}


Using this worked.