PIC32 Examples

From Steak Wiki
Revision as of 04:26, 30 October 2019 by Adminguy (talk | contribs) (Created page with "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...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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;
   
    
}