int main(void) { /* Disable JTAG to free up PORTA pins */ DDPCONbits.JTAGEN = 0; /* Set the lower 8 bits of PORTA as output (for Explorer-16 LEDs), clear the bits to ensure there is no mismatch when they are toggled */ PLIB_PORTS_DirectionOutputSet(PORTS_ID_0, PORT_CHANNEL_A, (PORTS_DATA_MASK)0x00FF); PLIB_PORTS_Clear(PORTS_ID_0, PORT_CHANNEL_A, (PORTS_DATA_MASK)0x00FF); /* Enable the DMA module */ PLIB_DMA_Enable(DMA_ID_0); /* Channel is continuously enabled */ PLIB_DMA_ChannelXAutoEnable(DMA_ID_0, DMA_CHANNEL_0); /* Set the source and destinaton addresses (addresses are converted from virtual to physical) */ PLIB_DMA_ChannelXSourceStartAddressSet(DMA_ID_0, DMA_CHANNEL_0, (uint32_t)LED_pattern); PLIB_DMA_ChannelXDestinationStartAddressSet(DMA_ID_0, DMA_CHANNEL_0, (uint32_t)&LATA); /* Set the source and destination sizes */ PLIB_DMA_ChannelXSourceSizeSet(DMA_ID_0, DMA_CHANNEL_0, sizeof(LED_pattern)); PLIB_DMA_ChannelXDestinationSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1); /* Set the number of bytes per transfer */ PLIB_DMA_ChannelXCellSizeSet(DMA_ID_0, DMA_CHANNEL_0, 1); /* DMA transfer to start on Timer 1 interrupt */ PLIB_DMA_ChannelXTriggerEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_CHANNEL_TRIGGER_TRANSFER_START); PLIB_DMA_ChannelXStartIRQSet(DMA_ID_0, DMA_CHANNEL_0, DMA_TRIGGER_TIMER_1); /* Setup Timer 1 to trigger an interrupt 10 times a second */ PLIB_TMR_ClockSourceSelect(TMR_ID_1, TMR_CLOCK_SOURCE_PERIPHERAL_CLOCK); PLIB_TMR_PrescaleSelect(TMR_ID_1, TMR_PRESCALE_VALUE_256); PLIB_TMR_Counter16BitClear(TMR_ID_1); PLIB_TMR_Period16BitSet(TMR_ID_1, 3906); /* Enable the Timer 1 interrupt source, set its priority level to 2, set its subpriority level to 0 */ PLIB_INT_SourceEnable(INT_ID_0, INT_SOURCE_TIMER_1); PLIB_INT_VectorPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_PRIORITY_LEVEL2); PLIB_INT_VectorSubPrioritySet(INT_ID_0, INT_VECTOR_T1, INT_SUBPRIORITY_LEVEL0); /* Enable multi-vectored interrupts, enable the generation of interrupts to the CPU */ PLIB_INT_MultiVectorSelect(INT_ID_0); PLIB_INT_Enable(INT_ID_0); /* Enable DMA channel 0 */ PLIB_DMA_ChannelXEnable(DMA_ID_0, DMA_CHANNEL_0); /* Start Timer 1 */ PLIB_TMR_Start(TMR_ID_1); /* Stuck in this loop, waiting for interrupts to occur */ while (1); /* Program should not go here during normal operation */ return EXIT_FAILURE; }
/* Function: SYS_MODULE_OBJ SYS_DMA_Initialize(const SYS_MODULE_INIT * const init) Summary: Initializes and Enables the DMA Controller. Description: This function Enables the DMA module. Enable/Disable stop in idle mode feature based on the passed parameter value. This routine initializes the DMA module making it ready for clients to open and use it. The initialization data is specified by the init parameter. Remarks: This routine must be called before any other DMA systems service routines are called. Not all features are available on all micro-controllers. */ SYS_MODULE_OBJ SYS_DMA_Initialize(const SYS_MODULE_INIT * const init) { SYS_DMA_INIT *initp; uint8_t chanIndex; SYS_DMA_CHANNEL_OBJECT *chanObj; /* Validate the init object */ if ((SYS_MODULE_INIT *)NULL == init) { SYS_ASSERT(false, "Invalid Init Object"); return SYS_MODULE_OBJ_INVALID; } initp = (SYS_DMA_INIT *)init; /* Enable/disable the stop in idle mode feature. */ #if defined (PLIB_DMA_ExistsStopInIdle) if(true == PLIB_DMA_ExistsStopInIdle(DMA_ID_0)) { if(SYS_DMA_SIDL_DISABLE == initp->sidl) { PLIB_DMA_StopInIdleDisable(DMA_ID_0); } else if(SYS_DMA_SIDL_ENABLE == initp->sidl) { PLIB_DMA_StopInIdleEnable(DMA_ID_0); } } #endif /* Enable the DMA module */ PLIB_DMA_Enable(DMA_ID_0); /* Initialize the available channel objects */ chanObj = (SYS_DMA_CHANNEL_OBJECT *)&gSysDMAChannelObj[0]; for(chanIndex = 0; chanIndex < SYS_DMA_CHANNEL_COUNT; chanIndex++) { chanObj->inUse = false; chanObj->pEventCallBack = NULL; chanObj->hClientArg = 0; chanObj->errorInfo = SYS_DMA_ERROR_NONE; chanObj = chanObj + 1; /* Initializing all channel priorities as 0 */ PLIB_DMA_ChannelXPrioritySelect(DMA_ID_0, chanIndex, chanIndex); } /* Return the object structure */ return ((SYS_MODULE_OBJ) initp); }
void IspSpiDMA_Rx(uint8_t *pbuf,uint16_t length) { bool intDisabled; unsigned char txTrash[3000]; // pbuf points to uint8_t array of data to be received from MRF // length indicates number of bytes to read intDisabled = WF_EintIsDisabled(); WF_EintDisable(); IEC1CLR=0x00030000; // disable DMA channel 0&1 interrupts IFS1CLR=0x00030000; // clear existing DMA channel 0&1 interrupt flag PLIB_DMA_Enable(0); // DMACONSET=0x00008000; // enable the DMA controller PLIB_DMA_ChannelXPrioritySelect(0,DMA_CHANNEL_0, DMA_CHANNEL_PRIORITY_3);//DCH0CONSET = 0x3; // channel off, pri 3, no chaining PLIB_DMA_ChannelXChainDisable(0,DMA_CHANNEL_0); PLIB_DMA_ChannelXPrioritySelect(0,DMA_CHANNEL_1, DMA_CHANNEL_PRIORITY_2);// DCH1CONSET = 0x03;//0x62; PLIB_DMA_ChannelXChainEnable(0,DMA_CHANNEL_1); DCH0ECONCLR=0xFFFFFFFF; // no start or stop irq?s, no pattern match DCH1ECONCLR=0xFFFFFFFF; // no start or stop irq?s, no pattern match // program the transfer PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_0, ((unsigned long int)txTrash) & 0x1FFFFFFFL); PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_1, ((unsigned long int)pbuf) & 0x1FFFFFFFL); if( MRF24W_SPI_CHN == 1) { PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_0, ((unsigned long int)&SPI1BUF) & 0x1FFFFFFFL); PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_1, ((unsigned long int)&SPI1BUF) & 0x1FFFFFFFL); } else if( MRF24W_SPI_CHN == 2) { PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_0, ((unsigned long int)&SPI2BUF) & 0x1FFFFFFFL); PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_1, ((unsigned long int)&SPI2BUF) & 0x1FFFFFFFL); } PLIB_DMA_ChannelXSourceSizeSet (0,DMA_CHANNEL_0,length); PLIB_DMA_ChannelXDestinationSizeSet(0,DMA_CHANNEL_0,1 ); PLIB_DMA_ChannelXCellSizeSet (0,DMA_CHANNEL_0,1 ); PLIB_DMA_ChannelXSourceSizeSet (0,DMA_CHANNEL_1,1); PLIB_DMA_ChannelXDestinationSizeSet(0,DMA_CHANNEL_1,length); PLIB_DMA_ChannelXCellSizeSet (0,DMA_CHANNEL_1,1 ); DCH0INTCLR=0x00ff00ff; // clear existing events, disable all interrupts DCH1INTCLR=0x00ff00ff; // clear existing events, disable all interrupts // initiate a transfer PLIB_DMA_ChannelXStartIRQSet(0, DMA_CHANNEL_0, DMA_TRIGGER_SPI_1_TRANSMIT); PLIB_DMA_ChannelXTriggerEnable(0, DMA_CHANNEL_0, DMA_CHANNEL_TRIGGER_TRANSFER_START); PLIB_DMA_ChannelXStartIRQSet(0, DMA_CHANNEL_1, DMA_TRIGGER_SPI_1_RECEIVE); PLIB_DMA_ChannelXTriggerEnable(0, DMA_CHANNEL_1, DMA_CHANNEL_TRIGGER_TRANSFER_START); PLIB_DMA_ChannelXEnable(0,DMA_CHANNEL_0); PLIB_DMA_ChannelXEnable(0,DMA_CHANNEL_1); // DCH0ECONSET=0x00000080; // set CFORCE to 1 // do something else // poll to see that the transfer was done while(true) { register int pollCnt; // use a poll counter. // continuously polling the DMA controller in a tight // loop would affect the performance of the DMA transfer int dma0Flags=DCH0INT; int dma1Flags = DCH1INT; if((dma0Flags&0xb)&&(dma1Flags&0xb)) { // one of CHERIF (DCHxINT<0>), CHTAIF (DCHxINT<1>) // or CHBCIF (DCHxINT<3>) flags set break; // transfer completed } pollCnt=length<<1; // use an adjusted value here while(pollCnt--); // wait before reading again the DMA controller } PLIB_DMA_Disable(0); if(!intDisabled) { WF_EintEnable(); } }