This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DMA and Interrupts

Hi,

I'm using a TMS570 running with Micrium µC/OS-III. I have written a DMA driver which currently works well except for one detail: the interrupts stay in a pending state. When testing with DMA channel 0, I've enabled bit 0 of register FTCINTENAS (FTC Interrupt Enable Set) and of register GCHIENAS (Global Channel Interrupt Enable Set Register). I've also made sure that the VIM module has the address of my interrupt handler and that it is enabled for the FTC interrupt. Nevertheless, my program never enters my interrupt handler. After the first execution, the values of an array are transfered to another array. Because register FTCAOFFSET (FTCA Interrupt Channel Offset Register) contains the value 1, I know my interrupt on channel 0 is pending.

Here is my current code :

/*
 * Project : Darius_TMS
 *
 * Module : /CSP/DMA
 *
 * File  : dma_driver.c
 *
 * Owner : DARIUS (Team #3 – gegi s7/s8 project)
       Université de Sherbrooke
 *
 * Status : UNFINISHED
 *
 *
 * Description : DMA Driver
 *
 * Modification History
 * --------------------
 *
 * Date   Version  Who  Description
 * ----------------------------------------------------------
 *
 * 2012-04-09 1.0.0  Maxime  Initial version
 *
 */



/*
*********************************************************************************************************
*                                             INCLUDE FILES
*********************************************************************************************************
*/

#include  <dma_driver.h>
#include  <csp.h>
#include  <log.h>

/*
*********************************************************************************************************
*                                            GLOBAL VARIABLES
*********************************************************************************************************
*/



/*
*********************************************************************************************************
*                                             LOCAL DEFINES
*********************************************************************************************************
*/

#define  VOID_PTR     ((CPU_VOID *) 0)

/*
*********************************************************************************************************
*                                            LOCAL VARIABLES
*********************************************************************************************************
*/

/* Registers */
static   DMAPrimaryCtrlPkt   *_PrimaryCtrlPkt[DMA_NBR_AVAILABLE_CHANNELS];
//static
#define  _SWChannelEnableReg   ((DMA_REG_SWCHENAS *)  DMA_REG_ADDR_SWCHENAS)
#define  _GlobalControlReg   ((DMA_REG_GCTRL *)  DMA_REG_ADDR_GCTRL)
#define  _PortAssignmentReg   ((DMA_REG_PAR *)  DMA_REG_ADDR_PAR0)
#define  _FTCInterruptEnableReg  ((DMA_REG_FTCINTENAS *) DMA_REG_ADDR_FTCINTENAS)
#define  _DMARequestAssignement  ((DMA_REG_DREQASI *)  DMA_REG_ADDR_DREQASI0)
#define  _FTCBInterruptOffsetReg  ((DMA_REG_FTCBOFFSET *) DMA_REG_ADDR_FTCBOFFSET)
#define  _GlobalChannelIntEnReg  ((DMA_REG_GCHIENAS *) DMA_REG_ADDR_GCHIENAS)

/* Interrupt argument */
static DMA_CHANNEL _ChannelIntArg;

/* Semaphores */
OS_MUTEX _DMATxMutex[DMA_NBR_AVAILABLE_CHANNELS];

/*
*********************************************************************************************************
*                                             FUNCTION PROTOTYPES
*********************************************************************************************************
*/

static void    DMAEnable();
static void    DMAReset();
static DMA_CHANNEL_CFG *DMASetChannelCfg(DMA_CHANNEL *channel,
           DMA_ELEM_SIZE *elementSize,
           CPU_INT32U  *initialSrcPtr,
           CPU_INT32U  *initialDestPtr,
           CPU_INT16U  *initialElemCount,
           CPU_BOOLEAN *isSrcIncremented,
           CPU_BOOLEAN *isDestIncremented);
static DMA_CHANNEL  DMAGetChannelNumber(DMA_CHANNEL_CFG *channel);
static void    DMAEnableInterrupt(DMA_CHANNEL *channel);
static void    DMAFTCInterruptHandler(void *p_arg);

/*
*********************************************************************************************************
*                                            DMA INIT
*
* Description : Initialize the DMA driver with the proper configuration.
*
* Arguments   : none
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

void DMAInit()
{
 _PrimaryCtrlPkt[0] = (DMAPrimaryCtrlPkt *) DMA_RAM_BASE_ADDRESS;
 _PrimaryCtrlPkt[1] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 1*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[2] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 2*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[3] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 3*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[4] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 4*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[5] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 5*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[6] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 6*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[7] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 7*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[8] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 8*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[9] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 9*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[10] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 10*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[11] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 11*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[12] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 12*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[13] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 13*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[14] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 14*sizeof(DMAPrimaryCtrlPkt));
 _PrimaryCtrlPkt[15] = (DMAPrimaryCtrlPkt *) (DMA_RAM_BASE_ADDRESS + 15*sizeof(DMAPrimaryCtrlPkt));

 DMAReset();

 DMAEnable();

 _GlobalControlReg->debugMode = DMA_DEBUG_MODE_IGNORE;

 CSP_IntVectReg(CSP_INT_CTRL_NBR_MAIN,          /* Link the interrupt to the interrupt handler    */
     CSP_INT_SRC_NBR_DMA_FRAME_XFER_COMP,
     DMAFTCInterruptHandler,
     VOID_PTR);

 CSP_IntEn(CSP_INT_CTRL_NBR_MAIN,           /* Enable the interrupt         */
    CSP_INT_SRC_NBR_DMA_FRAME_XFER_COMP);
}

/*
*********************************************************************************************************
*                                            DMA ADD CHANNEL
*
* Description : Set the DMA channel with the proper configuration.
*
* Arguments   : channel    Channel to configure.
*     elementSize   Size of an element. 8, 16, 32 or 64 bits.
*     *initialSrcPtr  Initial Source Pointer.
*     *initialDestPtr  Initial Destination Pointer.
*     initialElemCount Number of elements to transfer. Enter the maximum number of elements
*          you'll want to transfer. Value 0 - 0x1FFF.
*     *isSrcIncremented Determines if the source pointer is incremented.
*     *isDestIncremented Determines if the destination pointer is incremented.
*
* Returns     : DMA_CHANNEL_CFG * Pointer to the configuration of the channel.
*
* Notes       : none
*********************************************************************************************************
*/

DMA_CHANNEL_CFG * DMAAddChannel( DMA_CHANNEL channel,
         DMA_ELEM_SIZE elementSize,
         CPU_INT32U  *initialSrcPtr,
         CPU_INT32U  *initialDestPtr,
         CPU_INT16U  initialElemCount,
         CPU_BOOLEAN isSrcIncremented,
         CPU_BOOLEAN isDestIncremented)
{
 OS_ERR os_err;

 DMAEnableInterrupt(&channel);

 OSMutexCreate(&_DMATxMutex[channel],
    "DMA Tx Mutex",
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);

 DMA_CHANNEL_CFG *channelCfg;
 channelCfg = DMASetChannelCfg( &channel,
         &elementSize,
         initialSrcPtr,
         initialDestPtr,
         &initialElemCount,
         &isSrcIncremented,
         &isDestIncremented);

 return channelCfg;
}

/*
*********************************************************************************************************
*                                            DMA START TRANSFER
*
* Description : Start a DMA transfer.
*
* Arguments   : *channel  Channel number to start the transfer.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

void DMAStartTransfer(DMA_CHANNEL_CFG *channel)
{
 CPU_TS ts;
 OS_ERR os_err;

 DMA_CHANNEL channelNbr = DMAGetChannelNumber(channel);   /* Find which channel it is          */

 OSMutexPend(&_DMATxMutex[channelNbr],
    0,
    OS_OPT_PEND_BLOCKING,
    &ts,
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);

 _ChannelIntArg = channelNbr;         /* Argument to the interrupt handler       */

 _SWChannelEnableReg->channelEnable |= (1 << channelNbr);  /* Enable the proper channel         */
}

/*
*********************************************************************************************************
*                                            DMA CHANGE ELEM COUNT
*
* Description : Change the number of elements to be transfered.
*
* Arguments   : *channel  Pointer to channel address.
*     elemCount  Element count. Values range from 0 to 0x1FFF.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

void DMAChangeElemCount(DMA_CHANNEL_CFG *channel,
      CPU_INT16U  elemCount)
{
 CPU_TS ts;
 OS_ERR os_err;

 DMA_CHANNEL channelNbr = DMAGetChannelNumber(channel);   /* Find which channel it is          */

 OSMutexPend(&_DMATxMutex[channelNbr],       /* Make sure you're not transfering data      */
    0,
    OS_OPT_PEND_BLOCKING,
    &ts,
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);

 _PrimaryCtrlPkt[channelNbr]->initialTransferCount.initialElemCount  = elemCount;

 OSMutexPost(&_DMATxMutex[_ChannelIntArg],      /* Free the mutex            */
    OS_OPT_POST_NONE,
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);
}

/*
*********************************************************************************************************
*                                            DMA CHANGE DEST PTR
*
* Description : Change the destination pointer of the channel. Can help setting up a buffer.
*
* Arguments   : *channel  Pointer to channel address.
*     *destPtr  New destination pointer.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

void DMAChangeDestPtr( DMA_CHANNEL_CFG *channel,
      CPU_INT32U  *destPtr)
{
 CPU_TS ts;
 OS_ERR os_err;

 DMA_CHANNEL channelNbr = DMAGetChannelNumber(channel);   /* Find which channel it is          */

 OSMutexPend(&_DMATxMutex[channelNbr],
    0,
    OS_OPT_PEND_BLOCKING,
    &ts,
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);

 _PrimaryCtrlPkt[channelNbr]->initialDestAddr = destPtr;

 OSMutexPost(&_DMATxMutex[channelNbr],
    OS_OPT_POST_NONE,
    &os_err);

 LogOSError(DMA_DRIVER, &os_err);
}

/*
*********************************************************************************************************
*                                             INTERNAL ROUTINES
*********************************************************************************************************
*/

/*
*********************************************************************************************************
*                                            DMA ENABLE
*
* Description : Enable the use of the DMA controller.
*
* Arguments   : none
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

static void DMAEnable()
{
 _GlobalControlReg->dmaEnable = 1;

}

/*
*********************************************************************************************************
*                                            DMA RESET
*
* Description : Reset the DMA controller.
*
* Arguments   : none
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

static void DMAReset()
{
 OS_ERR os_err;

 _GlobalControlReg->dmaReset = 1;

 while (_GlobalControlReg->dmaReset == 1) {
  OSTimeDlyHMSM(0, 0, 0, 100,
       OS_OPT_TIME_HMSM_STRICT,
       &os_err);
 }
}

/*
*********************************************************************************************************
*                                            DMA SET CHANNEL CONFIGURATION
*
* Description : Set the DMA channel with the proper configuration.
*
* Arguments   : channel    Channel to configure.
*     elementSize   Size of an element. 8, 16, 32 or 64 bits.
*     *initialSrcPtr  Initial Source Pointer.
*     *initialDestPtr  Initial Destination Pointer.
*     *initialElemCount Number of elements to transfer. Value 0 - 0x1FFF.
*     *isSrcIncremented Determines if the source pointer is incremented.
*     *isDestIncremented Determines if the destination pointer is incremented.
*
* Returns     : DMA_CHANNEL_CFG * Pointer to the configuration of the channel.
*
* Notes       : none
*********************************************************************************************************
*/

static DMA_CHANNEL_CFG * DMASetChannelCfg( DMA_CHANNEL  *channel,
           DMA_ELEM_SIZE *elementSize,
           CPU_INT32U  *initialSrcPtr,
           CPU_INT32U  *initialDestPtr,
           CPU_INT16U  *initialElemCount,
           CPU_BOOLEAN  *isSrcIncremented,
           CPU_BOOLEAN  *isDestIncremented)
{
 _PrimaryCtrlPkt[*channel]->initialDestAddr  = initialDestPtr;
 _PrimaryCtrlPkt[*channel]->initialSourceAddr = initialSrcPtr;

 _PrimaryCtrlPkt[*channel]->initialTransferCount.initialElemCount  = *initialElemCount;
 _PrimaryCtrlPkt[*channel]->initialTransferCount.initialFrameCount = 1;

 _PrimaryCtrlPkt[*channel]->channelConfiguration.chain     = DMA_CHAIN_NO_CHANNEL;
 _PrimaryCtrlPkt[*channel]->channelConfiguration.readElemSize   = *elementSize;
 _PrimaryCtrlPkt[*channel]->channelConfiguration.writeElemSize   = *elementSize;
 _PrimaryCtrlPkt[*channel]->channelConfiguration.transferType  = DMA_TTYPE_HARDWARE_FRAME;
 _PrimaryCtrlPkt[*channel]->channelConfiguration.autoInitiationMode  = DMA_AIM_ENABLED;

 _PrimaryCtrlPkt[*channel]->channelConfiguration.addressingModeRead  = DMA_ADDRM_INDEXED;
 _PrimaryCtrlPkt[*channel]->channelConfiguration.addressingModeWrite = DMA_ADDRM_INDEXED;

 if (isDestIncremented) {
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.destAddrIdx  = 1;
 }
 else {
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.destAddrIdx  = 0;
 }
 if (isSrcIncremented) {
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.sourceAddrIdx  = 1;
 }
 else {
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.sourceAddrIdx  = 0;
 }

 CPU_INT16U i;
 for (i = 0; i < *elementSize; i++) {          /* To calculate the size of the offset in bytes   */
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.destAddrIdx  = _PrimaryCtrlPkt[*channel]->elemIdxOffset.destAddrIdx   << 1;
  _PrimaryCtrlPkt[*channel]->elemIdxOffset.sourceAddrIdx  = _PrimaryCtrlPkt[*channel]->elemIdxOffset.sourceAddrIdx << 1;
 }

 _PrimaryCtrlPkt[*channel]->frameIdxOffset.destAddrIdx  = 0;
 _PrimaryCtrlPkt[*channel]->frameIdxOffset.sourceAddrIdx = 0;    /* Always 0            */

 _PortAssignmentReg->channelPortAssignment[*channel].CHxPA = DMA_PA_PORT_B;

 return (DMA_CHANNEL_CFG *) _PrimaryCtrlPkt[*channel];
}

/*
*********************************************************************************************************
*                                            DMA GET CHANNEL NUMBER
*
* Description : Determines which channel number is associated with an address.
*
* Arguments   : *channel  Channel definition.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

static DMA_CHANNEL DMAGetChannelNumber(DMA_CHANNEL_CFG *channel)
{
 return (DMA_CHANNEL) (((CPU_INT32U)channel - (CPU_INT32U)DMA_RAM_BASE_ADDRESS) / (CPU_INT32U)DMA_PKT_PRIMARY_BASE_OFFSET);
}

/*
*********************************************************************************************************
*                                            DMA ENABLE INTERRUPT
*
* Description : Enable interrupt for a channel.
*
* Arguments   : *channel  Channel number.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/
static void    DMAEnableInterrupt(DMA_CHANNEL *channel)
{
 _GlobalChannelIntEnReg->GCHIE |= (1 << *channel);
 _FTCInterruptEnableReg->FTCInterruptEnable |= (1 << *channel);
}

/*
*********************************************************************************************************
*                                            DMA INTERUPT HANDLER
*
* Description : DMA Frame Transfer Complete interrupt handler
*
* Arguments   : *p_arg  Pointer to the arguments list. No arguments are defined at the moment.
*
* Returns     : none
*
* Notes       : none
*********************************************************************************************************
*/

static void DMAFTCInterruptHandler(void *p_arg)
{
 (void)p_arg;

 OS_ERR os_err;

 /*
 Log(DMA_DRIVER, 0x00, "DMA FTC Interrupt");
 Log(DMA_DRIVER, 0x00, "Valeur FTCB : %d", _FTCBInterruptOffsetReg->FTCB);
 */

 OSMutexPost(&_DMATxMutex[_ChannelIntArg],
        OS_OPT_POST_NONE,
        &os_err);

 /*
 LogOSError(DMA_DRIVER, &os_err);
 */
}

In the previous code, I know the following lines work quite well for SPI and ADC, so I see no reason why it shouldn't work with the DMA module. As I said, I've checked the registers of the VIM module and everything is fine. CSP_INT_SRC_NBR_DMA_FRAME_XFER_COMP value is 33 like it is specified in the datasheet.

 CSP_IntVectReg(CSP_INT_CTRL_NBR_MAIN,          /* Link the interrupt to the interrupt handler    */
     CSP_INT_SRC_NBR_DMA_FRAME_XFER_COMP,
     DMAFTCInterruptHandler,
     VOID_PTR);
 CSP_IntEn(CSP_INT_CTRL_NBR_MAIN,           /* Enable the interrupt         */
    CSP_INT_SRC_NBR_DMA_FRAME_XFER_COMP);

Do you see what I am doing wrong?

Thanks in advance,

Maxime

  • maxime,

    Thanks for the post i will look into it and get back to you.

     

    Hercules forum support

  • maxime,

    From the symptoms you have mentioned it looks like the DMA is triggering an interrupt . Can you check whther the corresponding channel is getting set in the INTREQ register of the VIM. . Also make sure that the CPU's CPSR is configured properly for its I bit.

     

    Hercules forum support

  • Hi Hari,

    Thank you for your fast reply. The INTREQ1 bit 0 register is 0. Also, the I bit of the CPSR is 0. Apart from setting registers FTCINTENAS  and GCHIENAS, is there anything else that needs to be done?

    Regards,

    Maxime

  • maxime,

    i suspect the VIM programmation is not happening properly pls refer to section 5 of the inserted app note which thelps you  in programmation of the VIM

  • I'm a collegue of Maxime...


    We're certain the VIM is configured correctly, since registers contains adresses to the correct location, up to the ISR Handler that should get called. As other indication, other peripheral's interrupts works correctly!


    Below are screenshots of the important registers, where you'll see that the interruptions are pending (FTCIntFlg, BTCIngtFlg, GlbIntFlg)...


    P.S. We are using Channel 0


    Dma   

                GlbCtrl           0x00010000    Global Control Register [Memory Mapped]

                ChnPnd          0x00000000    Channel Pending Register [Memory Mapped]        

                Stat     0x00000000    Status Register [Memory Mapped]  

                HWChnEnaSet          0x00000000    H/W Channel Enable Set and Status Register [Memory Mapped] 

                HWChnEnaRst          0x00000000    H/W Channel Enable Reset and Status Register [Memory Mapped]           

                SWChnEnaSet           0x00000000    S/W Channel Enable Set and Status Register [Memory Mapped]  

                SWChnEnaRst           0x00000000    S/W Channel Enable Reset and Status Register [Memory Mapped]           

                ChnPrioSet     0x00000000    Channel Priority Set Register [Memory Mapped]   

                ChnPrioRst     0x00000000    Channel Priority Reset [Memory Mapped]  

                GlbChnIntEnaSet      0x00000001    Global Channel Interrupt Enable Set [Memory Mapped]   

                GlbChnIntEnaRst      0x00000001    Global Channel Interrupt Enable Reset [Memory Mapped]

                ReqAssg0       0x00010203    Request Assignment Register 0 [Memory Mapped]

                ReqAssg1       0x04050607    Request Assignment Register 1 [Memory Mapped]

                ReqAssg2       0x08090A0B  Request Assignment Register 2 [Memory Mapped]

                ReqAssg3       0x0C0D0E0F Request Assignment Register 3 [Memory Mapped]

                ReqAssg4       0x10111213    Request Assignment Register 4 [Memory Mapped]

                ReqAssg5       0x14151617    Request Assignment Register 5 [Memory Mapped]

                ReqAssg6       0x18191A1B  Request Assignment Register 6 [Memory Mapped]

                ReqAssg7       0x1C1D1E1F Request Assignment Register 7 [Memory Mapped]

                PrtAssg0         0x60000000    Port Assignment Register 0 [Memory Mapped]      

                PrtAssg1         0x00000000    Port Assignment Register 1 [Memory Mapped]      

                PrtAssg2         0x00000000    Port Assignment Register 2 [Memory Mapped]      

                PrtAssg3         0x00000000    Port Assignment Register 3 [Memory Mapped]      

                FTCMap         0x00000000    FTC Interrupt Mapping Register [Memory Mapped]          

                LFSMap         0x00000000    LFS Interrupt Mapping Register [Memory Mapped]          

                HBCMap        0x00000000    HBC Interrupt Mapping Register [Memory Mapped]         

                BTCMap         0x00000000    BTC Interrupt Mapping Register [Memory Mapped]         

                BERMap        0x00000000    BER Interrupt Mapping Register [Memory Mapped]         

                FTCIntEnaSet            0x00000000    FTC Interrupt Enable Set [Memory Mapped]         

                FTCIntEnaRst            0x00000000    FTC Interrupt Enable Reset [Memory Mapped]      

                LFSIntEnaSet            0x00000000    LFS Interrupt Enable Set [Memory Mapped]          

                LFSIntEnaRst            0x00000000    LFS Interrupt Enable Reset [Memory Mapped]      

                HBCIntEnaSet           0x00000000    HBC Interrupt Enable Set [Memory Mapped]        

                HBCIntEnaRst          0x00000000    HBC Interrupt Enable Reset [Memory Mapped]    

                BTCIntEnaSet           0x00000001    BTC Interrupt Enable Set [Memory Mapped]         

                BTCIntEnaRst           0x00000001    BTC Interrupt Enable Reset [Memory Mapped]     

                GlbIntFlg        0x00000001    Global Interrupt Flg Register [Memory Mapped]    

                FTCIntFlg      0x00000001    FTC Interrupt Flag Register [Memory Mapped]     

                LFSIntFlg       0x00000001    LFS Interrupt Flag Register [Memory Mapped]      

                HBCIntFlg     0x00000001    HBC Interrupt Flag Register [Memory Mapped]    

                BTCIntFlg      0x00000001    BER Interrupt Flag Register [Memory Mapped]     

                BERIntFlg      0x00000000    BER Interrupt Flag Register [Memory Mapped]     

                FTCAOffst     0x00000000    FTCA Interrupt Channel Offset Register [Memory Mapped]        

                LFSAOffst     0x00000000    LFSA Interrupt Channel Offset Register [Memory Mapped]        

                HBCAOffst   0x00000000    HBCA Interrupt Channel Offset Register [Memory Mapped]       

                BTCAOffst    0x00000001    BTCA Interrupt Channel Offset Register [Memory Mapped]        

                BERAOffst    0x00000000    BERA Interrupt Channel Offset Register [Memory Mapped]       

                FTCBOffst     0x00000000    FTCB Interrupt Channel Offset Register [Memory Mapped]        

                LSFBOffst     0x00000000    LFSB Interrupt Channel Offset Register [Memory Mapped]         

                HBCBOffst    0x00000000    HBCB Interrupt Channel Offset Register [Memory Mapped]       

                BTCBOffst    0x00000000    BTCB Interrupt Channel Offset Register [Memory Mapped]        

                BERBOffst    0x00000000    BERB Interrupt Channel Offset Register [Memory Mapped]        

                PrtCtrl 0x00000000    Port Control Register [Memory Mapped]    

                RamTstCtrl     0x00000000    RAM TEST Control [Memory Mapped]      

                DbgCtrl          0x00000000    Debug Control [Memory Mapped]   

                WpReg           0x00000000    Watchpoint Register [Memory Mapped]     

                WpMsk           0x00000000    Watchpoint Mask Register [Memory Mapped]       

                PrtAChnSrcAddr       0x00000000    Port A Active Channel Source Address Register [Memory Mapped]           

                PrtAChnDstAddr      0x00000000    Port A Active Channel Destination Address Register [Memory Mapped]           

                PrtAChnTrCnt           0x00000000    Port A Active Channel Transfer Count Register [Memory Mapped]           

                PrtBChnSrcAddr       0x08020150    Port B Active Channel Source Address Register [Memory Mapped]           

                PrtBChnDestAddr     0x0802015C   Port B Active Channel Destination Address Register [Memory Mapped]           

                PrtBChnTrCnt            0x00000000    Port B Active Channel Transfer Count Register [Memory Mapped]           

                ParCtrl            0x00000005    Parity Control Register [Memory Mapped] 

                ParErrAddr     0x00000B00   Parity Error Address Register [Memory Mapped]   

                MpCtrl            0x00000000    Memory Protection Control Register [Memory Mapped]   

                MpStat            0x00000000    Memory Protection Status Register [Memory Mapped]      

                Pr0Strt            0x00000000    Start Address of region 0 [Memory Mapped]         

                Pr0End           0x00000000    End Address of region 0 [Memory Mapped]          

                Pr1Strt            0x00000000    Start Address of region 0 [Memory Mapped]         

                Pr1End           0x00000000    End Address of region 1 [Memory Mapped]          

                Pr2Strt            0x00000000    Start Address of region 2 [Memory Mapped]         

                Pr2End           0x00000000    End Address of region 2 [Memory Mapped]          

                Pr3Strt            0x00000000    Start Address of region 3 [Memory Mapped]         

                Pr3End           0x00000000    End Address of region 3 [Memory Mapped]         

    Vim    

                IrqIVec           0x00000000    Index Offset Vector Register [Memory Mapped]   

                FiqIVec          0x00000000    Index Offset Vector Register [Memory Mapped]   

                FIrqPr0           0x28110003    Program Control Register [Memory Mapped]         

                FIrqPr1           0x00420E08   Program Control Register [Memory Mapped]         

                FIrqPr2           0x00008000    Program Control Register [Memory Mapped]         

                IntReq0          0x00000000    Pending Interrupt Read Location [Memory Mapped]         

                IntReq1          0x00000100    Pending Interrupt Read Location [Memory Mapped]         

                IntReq2          0x00000000    Pending Interrupt Read Location [Memory Mapped]         

                ReqMaskSet0 0x0000200B   Interrupt Mask Set Register [Memory Mapped]      

                ReqMaskSet1 0x00000080    Interrupt Mask Set Register [Memory Mapped]      

                ReqMaskSet2 0x00000000    Interrupt Mask Set Register [Memory Mapped]      

                ReqMaskClr0 0x0000200B   Interrupt Mask Clear Register [Memory Mapped]  

                ReqMaskClr1 0x00000080    Interrupt Mask Clear Register [Memory Mapped]  

                ReqMaskClr2 0x00000000    Interrupt Mask Clear Register [Memory Mapped]  

                WakeMaskSet0          0xFFFFFFFF  Wake-up Mask Set Register [Memory Mapped]     

                WakeMaskSet1          0xFFFFFFFF  Wake-up Mask Set Register [Memory Mapped]     

                WakeMaskSet2          0xFFFFFFFF  Wake-up Mask Set Register [Memory Mapped]     

                WakeMaskClr0          0xFFFFFFFF  Wake-up Mask Clear Register [Memory Mapped]  

                WakeMaskClr1          0xFFFFFFFF  Wake-up Mask Clear Register [Memory Mapped]  

                WakeMaskClr2          0xFFFFFFFF  Wake-up Mask Clear Register [Memory Mapped]  

                IrqVecReg      0x0001ACF4  Irq Interrupt Vector Register [Memory Mapped]    

                FiqVecReg     0x0001ACF4  Fiq Interrupt Vector Register [Memory Mapped]   

                CapEvtSrc      0x00000000    Capture Event register [Memory Mapped]  

                ChanCtrl0       0x00010203    Channel Mapping Register [Memory Mapped]       

                ChanCtrl1       0x04050607    Channel Mapping Register [Memory Mapped]       

                ChanCtrl2       0x08090A0B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl3       0x0C0D0E0F Channel Mapping Register [Memory Mapped]       

                ChanCtrl4       0x10111213    Channel Mapping Register [Memory Mapped]       

                ChanCtrl5       0x14151617    Channel Mapping Register [Memory Mapped]       

                ChanCtrl6       0x18191A1B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl7       0x1C1D1E1F Channel Mapping Register [Memory Mapped]       

                ChanCtrl8       0x20212223    Channel Mapping Register [Memory Mapped]       

                ChanCtrl9       0x24252627    Channel Mapping Register [Memory Mapped]       

                ChanCtrl10     0x28292A2B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl11     0x2C2D2E2F Channel Mapping Register [Memory Mapped]       

                ChanCtrl12     0x30313233    Channel Mapping Register [Memory Mapped]       

                ChanCtrl13     0x34353637    Channel Mapping Register [Memory Mapped]       

                ChanCtrl14     0x38393A3B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl15     0x3C3D3E3F Channel Mapping Register [Memory Mapped]       

                ChanCtrl16     0x40414243    Channel Mapping Register [Memory Mapped]       

                ChanCtrl17     0x44454647    Channel Mapping Register [Memory Mapped]       

                ChanCtrl18     0x48494A4B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl19     0x4C4D4E4F Channel Mapping Register [Memory Mapped]       

                ChanCtrl20     0x50515253    Channel Mapping Register [Memory Mapped]       

                ChanCtrl21     0x54555657    Channel Mapping Register [Memory Mapped]       

                ChanCtrl22     0x58595A5B  Channel Mapping Register [Memory Mapped]       

                ChanCtrl23     0x5C5D5E5F Channel Mapping Register [Memory Mapped]       



    Question: How would that bit get cleared, what might be missing for the interruption to get fired when it's pending?

  • Hi Hari,

    I've read your document, but it's not pertinent to my problem because it shows how to make interrupts work with a GPIO. Interrupts work in my system. I can trigger the interrupts for ADC, I2C and SPi. My problem is that the DMA interrupts (FTC, BTC, etc.) stay in a pending state. I've tried a lot of things and still can't find any way to make the DMA interrupts work.

    What are the registers that need to be enabled?

    I've joined an example of the code to this post.

    1070.Darius_TMS_init.rar

  • Maxime,

    Thanks for sharing your code. This is really helpful.

    I was able to debug your code and I found out what is wrong. (I should say missing)

    You are using DMA Interrupt for BTC (Block Transfer Complete) This is done correctly, and this flag is correctly set in the DMA module once the transfer is done.
    What you are missing is the fact that there is a global enable bit to be set to allow the DMA module to send the request to the VIM.

    This is done via Global Channel Interrupt Enable Set Register (GCHIENAS) [offset = 44h]

    Another little mistake is on the VIM channel request. As per the datasheet, the DMA_BTCA interrupt is mapped to VIM Request 40.
    In CSP_IntEn, you end up enabling request 39 instead of 40.

    Because of this mistake, your VIM RAM for channel 40 is incorrect. Remember that the first VIM RAM location is for the phantom interrupt.
    Request line 0 is mapped that VIM_RAM_BASE + 0x04
    Request line 1 is mapped that VIM_RAM_BASE + 0x08 ......

    The content of VIM_RAM is the address of your interrupt handler for a given request.
    I did check the content of the VIM RAM in your application and the address stored for your DMA handler is incorrect. You have stored in VIM RAM is the address of a pointer, not the DMA handler entry point.

    Please let me know if this makes sense.

  • Hi Jean-Marc,

    Thank you for your reply. This solved my problem.

    In most of my tests, the GCHIENAS register was set. I must have sent the wrong version of my code. The real problem was, as you mentioned it, the bit 39 was enabled instead of the bit 40 in the REQENASET[1] register of the VIM. Also, as you said, the address in the VIM_RAM was off by 0x04. I'll report those bugs to Micrium, which made the OS I'm currently using, and how it was fixed.

    "You have stored in VIM RAM is the address of a pointer, not the DMA handler entry point."

    It's true, but the pointer points on the DMA handler entry point. This is why it still works.

    Thank you for your help!

    Maxime

  • Maxime,

    Good to read that it is working now.

    Concerning the VIM RAM content, it is working because you are not using the VIM and CPU in Hardware vector mode but in legacy mode.
    In case of IRQ or FIQ, the CPU is jumping in 0x18 or 0x1C and than you execute your IRQ_Handler or FIQ_Handler.

    In Hardware Vector mode, the VIM will provide the entry point of the exception handler directly. The cpu does not go anymore to 0x18.
    In this case, the VIM_RAM content has to be the address of the routine, cannot be a pointer to this address.
    I just wanted to highlight this point.
    When an OS is use, your option is the correct one. It is necessary for the OS to intercept all interrupt and decide how to deal with them.