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; }
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(); } }
void SYS_DMA_ChannelSetup ( SYS_DMA_CHANNEL_HANDLE handle, SYS_DMA_CHANNEL_OP_MODE modeEnable, DMA_TRIGGER_SOURCE eventSrc ) { SYS_DMA_CHANNEL_OBJECT *chanObj; DMA_CHANNEL channelNumber; chanObj = (SYS_DMA_CHANNEL_OBJECT *) handle; channelNumber = (chanObj - (SYS_DMA_CHANNEL_OBJECT *) &gSysDMAChannelObj[0]); /* Setup the channel modes */ /* Basic mode, nothing specifically needs to be set */ if(SYS_DMA_CHANNEL_OP_MODE_BASIC & modeEnable) { /* Do nothing */ ; } /* Pattern match Abort */ if(SYS_DMA_CHANNEL_OP_MODE_MATCH_ABORT & modeEnable) { PLIB_DMA_ChannelXTriggerEnable( DMA_ID_0, channelNumber, DMA_CHANNEL_TRIGGER_PATTERN_MATCH_ABORT); } /* Channel chaining mode */ if(SYS_DMA_CHANNEL_OP_MODE_CHAIN_HIGH & modeEnable) { PLIB_DMA_ChannelXChainEnable( DMA_ID_0, channelNumber); PLIB_DMA_ChannelXChainToHigher(DMA_ID_0, channelNumber); PLIB_DMA_ChannelXDisabledEnablesEvents(DMA_ID_0, channelNumber); } else if(SYS_DMA_CHANNEL_OP_MODE_CHAIN_LOW & modeEnable) { PLIB_DMA_ChannelXChainEnable( DMA_ID_0, channelNumber); PLIB_DMA_ChannelXChainToLower(DMA_ID_0, channelNumber); PLIB_DMA_ChannelXDisabledEnablesEvents(DMA_ID_0, channelNumber); } else { ; } /* Auto Enable mode */ if(SYS_DMA_CHANNEL_OP_MODE_AUTO & modeEnable) { PLIB_DMA_ChannelXAutoEnable( DMA_ID_0, channelNumber); } /* CRC Enable */ if(SYS_DMA_CHANNEL_OP_MODE_CRC & modeEnable) { PLIB_DMA_CRCEnable( DMA_ID_0); } /* Setup the DMA Trigger Source and Enable it */ if(DMA_TRIGGER_SOURCE_NONE == eventSrc) { /* This is polling mode of Implementation */ PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, channelNumber, DMA_INT_BLOCK_TRANSFER_COMPLETE); PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, channelNumber, DMA_INT_ADDRESS_ERROR); } else { PLIB_DMA_ChannelXStartIRQSet( DMA_ID_0, channelNumber, eventSrc); PLIB_DMA_ChannelXTriggerEnable( DMA_ID_0, channelNumber, DMA_CHANNEL_TRIGGER_TRANSFER_START); /* We need to notify the user on the completion of a transfer request. * Setting the DMA block completion transfer interrupt. */ PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, channelNumber, DMA_INT_BLOCK_TRANSFER_COMPLETE); PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, channelNumber, DMA_INT_ADDRESS_ERROR); } return; }