PIC32 Examples
From Steak Wiki
Jump to navigationJump to search
I need somewhere to put my scraps of code. These may or may not work.
DMA SPI
Also covered by peripheral libraries example. Must have RX and TX enabled (for MX). RX must empty buffer. Everything put into TX, goes into RX (they share buffer). Therefore, you must use two DMA channels to use SPI and DMA to SDO something.
Goes like this:
- TX puts something into buffer
- SDO outputs thing
- SPIxRXREG now contains thing also
- Transfer via DMA SPIxRXREG to memory
- continue until DCHxSSIZ is complete (note that some MX are 8 bits for SSIZ, while some later are 16 bits)
If you can't keep up with the RX, and it overflows, there is a flag that is set. ROVR I think.
void configureSPI_DMA (void){ //we put things in dma buffer, and it sends to spi, without cpu involvement //channel 1 DCH1INT = 0; //disable all dma interrupts IEC1bits.DMA1IE = 0x00; //disable DMA channel 1 interrupts IFS1bits.DMA1IF = 0x00; //clear any existing dma flags DCH1CONbits.CHPRI = 0b10; //second priority //this doesn't work //DCH1INTbits.CHCCIE = 1; //ENABLE not flag. Don't mix these up... //cell transfer status flag was the only one //going high, so set it to that instead of block. DCH1INTbits.CHBCIE = 1; //interrupt dma, when block transfer done. eq to DMA_EV_BLOCK //this didn't work. I put a watch on that register flag //but it never caught in the main loop. however, others do. //edit: this does work. DCH1ECONbits.CHSIRQ = 38; //spi 2 transfer done (this activates the dma) //this below doesn't work //DCH1ECONbits.CHSIRQ = 49; //EDIT:I think you use not SPI, but the DMA interrupts. //when a block transfer is done, you do another one. //there are a few interrupts, see DCH1INT, for what you //can use, and also the flags that are set can be watched. DCH1ECONbits.SIRQEN = 1; //req'd for chsirq, in order to work DCH1CONbits.CHAEN = 0; //channel is automatically enabled, after transfer //Source, Destination, Source size, Dest Size, bytes transfer //DCH1SSA = KVA_TO_PA(spiregisters); //source address (has values) DCH1SSA = KVA_TO_PA(testRGB); //source address (has values) //DCH1SSA = KVA_TO_PA(testsimple); //this works when padding testsimple array with some zeros, but not if just 0x3,0x4,0x5 //DCH1SSA = KVA_TO_PA(&dmatoram[0]); //source address (blank zeros) //DCH1DSA = KVA_TO_PA(&SPI2BUF); //destination address DCH1DSA = KVA_TO_PA(&SPI2BUF); DCH1SSIZ = 1000; //9643 //source size (1 byte) DCH1DSIZ = 1; //destination size max DCH1SPTR; //pointer of where source is DCH1DPTR; DCH1CSIZ = 1; //bytes transferred on an event //NOTE: This has to be equal to source, and dest, if both //source and dest are RAM. Not so for UART though. //priority,flag,enable (for interrupts) IPC9bits.DMA1IP = 0x00; //clear priority IPC9bits.DMA1IS = 0x00; //clear sub priority IPC9bits.DMA1IP = 4; //set priority 5 IPC9bits.DMA1IS = 2; //clear sub priority DMACON; DMASTAT; DCH1CON; DCH1ECON; DCH1INT; IEC1bits.DMA1IE = 1; //enable interrupts DMACONbits.ON = 1; //global dma enable (already enabled, technically) DCH1CONbits.CHEN = 1; //enables channel //after neobit fills spiregisters, do this...? //DCH1ECONbits.CFORCE = 1; //run once IEC1; IFS1; IPC9; } //rx dma void configureSPIRXDMA(void){ DCH2INT = 0; //disable all dma interrupts IEC1bits.DMA2IE = 0x00; //disable DMA channel 1 interrupts IFS1bits.DMA2IF = 0x00; //clear any existing dma flags DCH2CONbits.CHPRI = 0b10; //second priority //this doesn't work //DCH1INTbits.CHCCIE = 1; //ENABLE not flag. Don't mix these up... //cell transfer status flag was the only one //going high, so set it to that instead of block. //DCH2INTbits.CHBCIE = 1; //interrupt dma, when block transfer done. eq to DMA_EV_BLOCK //this didn't work. I put a watch on that register flag //but it never caught in the main loop. however, others do. //edit: this does work. DCH2ECONbits.CHSIRQ = 39; //spi 2 receive done (this activates the dma) //this below doesn't work //DCH1ECONbits.CHSIRQ = 49; //EDIT:I think you use not SPI, but the DMA interrupts. //when a block transfer is done, you do another one. //there are a few interrupts, see DCH1INT, for what you //can use, and also the flags that are set can be watched. DCH2ECONbits.SIRQEN = 1; //req'd for chsirq, in order to work DCH2CONbits.CHAEN = 0; //channel is automatically enabled, after transfer DCH2SSA = KVA_TO_PA(&SPI2BUF); //source address (has values) DCH2DSA = KVA_TO_PA(spirxbuf); DCH2SSIZ = 1; //9643 //source size (1 byte) DCH2DSIZ = 1000; //destination size max DCH2SPTR; //pointer of where source is DCH2DPTR; DCH2CSIZ = 1; //bytes transferred on an event //NOTE: This has to be equal to source, and dest, if both //source and dest are RAM. Not so for UART though. DCH2CONbits.CHCHNS = 0; //chain to channel higher up (1) DCH2CONbits.CHCHN = 1; //enable chain channel IPC9bits.DMA2IP = 0x00; //clear priority IPC9bits.DMA2IS = 0x00; //clear sub priority IPC9bits.DMA2IP = 4; IPC9bits.DMA2IS = 3; DMACON; DMASTAT; DCH2CON; DCH2ECON; DCH2INT; //DMACONbits.ON = 1; //global dma enable (already enabled, technically) DCH2CONbits.CHEN = 1; //enables channel IEC1; IFS1; IPC9; IEC1bits.DMA2IE = 1; //enable dma interrupts IPC9bits.DMA2IP = 7; IPC9bits.DMA2IS = 3; }