SPI slave program to enable communication between the FPGA and the STM32L432 board.

Dependencies:   mbed

Revision:
15:791f35b0f220
Parent:
14:7bbaafa22f8d
--- a/DMA_SPI.cpp	Sun May 05 01:08:22 2019 +0000
+++ b/DMA_SPI.cpp	Wed May 15 22:56:20 2019 +0000
@@ -30,6 +30,7 @@
     startCommunication();     
 }    
 
+//-----------------------------------------------Step-5-----------------------------------------------------------------------------------------------------------
 /* Starting DMA communication according to STM32L432 Reference Manual p1317-p1318*/
 void startCommunication() {
     
@@ -149,91 +150,97 @@
 
 
 void SPI_DMA_SLAVE_init() {
-    RCC->AHB2ENR|= (RCC_AHB2ENR_GPIOAEN);                                       //GPIO A clock enable
-    RCC->AHB2ENR |= (RCC_AHB2ENR_GPIOBEN);      
-    RCC->APB2ENR|=RCC_APB2ENR_SPI1EN;                                           //Enable SPI1 Clock
+    //-----------------------------------------------Step-1-----------------------------------------------------------------------------------------------------------
+    RCC->AHB2ENR|= (RCC_AHB2ENR_GPIOAEN);                                       //GPIO A clock enable by setting the GPIOAEN bit in the RCC_AHB2ENR register
+    RCC->AHB2ENR |= (RCC_AHB2ENR_GPIOBEN);                                      //GPIO B clock enable by setting the GPIOBEN bit in the RCC_AHB2ENR register
+    RCC->APB2ENR|=RCC_APB2ENR_SPI1EN;                                           //Enable SPI1 Clock by setting the SPI1EN bit in the RCC_APB2ENR register
 
-   //SET SCK, MISO, MOSI and CS pins 
+    //-----------------------------------------------Step-2-----------------------------------------------------------------------------------------------------------
+    //SET SCK, MISO, MOSI and CS pins 
     GPIOA->MODER|=(                                                             
-            (2u<<(2*SCK_slave))
-            |(2u<<(2*MISO_slave))
-            |(2u<<(2*MOSI_slave))
+            (2u<<(2*SCK_slave))                                                 //Set pin 1 in the MODER register of port A as alternate function
+            |(2u<<(2*MISO_slave))                                               //Set pin 6 in the MODER register of port A as alternate function
+            |(2u<<(2*MOSI_slave))                                               //Set pin 7 in the MODER register of port A as alternate function
             //|(2u<<(2*4))
                 );
     //Set PB_0 to alternate function
-    GPIOB->MODER |= (2u<<0);
-                
+    GPIOB->MODER |= (2u<<0);                                                    //Set pin 0 in the MODER register of port B as alternate function    
+            
+    //-----------------------------------------------Step-3-----------------------------------------------------------------------------------------------------------            
     //SET pins to function as SPI pins
-    GPIOA->AFR[0]|=(                                                             
-            (5u<<(4*SCK_slave))
-            |(5u<<(4*MISO_slave))
-            |(5u<<(4*MOSI_slave))
+    GPIOA->AFR[0]|=(                                                                                                           
+            (5u<<(4*SCK_slave))                                                 //Set the alternate function of pin 1 as SPI clock pin by writing 1001 to the lower part of the AFR register of port A.
+            |(5u<<(4*MISO_slave))                                               //Set the alternate function of pin 6 as SPI MISO pin by writing 1001 to the lower part of the AFR register of port A.
+            |(5u<<(4*MOSI_slave))                                               //Set the alternate function of pin 7 as SPI clock pin by writing 1001 to the lower part of the AFR register of port A.
             //|(5u<<(4*4))
                 );
     
     //Select SPI1_SSEL alternate function          
-    GPIOB->AFR[0] |= (5u<<(4*0));
-                
+    GPIOB->AFR[0] |= (5u<<(4*0));                                               //Set the alternate function of pin 0 as SPI slave select pin by writing 1001 to the lower part of the AFR register of port B.
+    
+    //-----------------------------------------------Step-4-----------------------------------------------------------------------------------------------------------            
     SET_SPI1_CR1_BR_BITS();                                                     //baud rate bits set 1/16 giving 1MHz SCK frequency
+    //-----------------------------------------------Step-5-----------------------------------------------------------------------------------------------------------
     SET_SPI1_CR1_CPOL_BIT();                                                    //CPOL = 1
     SET_SPI1_CR1_CPHA_BIT();                                                    //CPHA = 1                                                  
     
-    
+    //-----------------------------------------------Step-6-----------------------------------------------------------------------------------------------------------
     SET_SPI1_CR2_DS_BITS();                                                     //Data Size = 16 bits
    // SET_SPI1_CR2_RXDMAEN_BIT();                                                 //Rx buffer DMA enable
-   // SET_SPI1_CR2_TXDMAEN_BIT();                                                 //Tx buffer DMA enable
-
-    
+   // SET_SPI1_CR2_TXDMAEN_BIT();                                                 //Tx buffer DMA enable  
 }
 
-
-
+   //SET_DMA1_CH2_CCR_PINC_BIT();                                               //Peripheral increment mode
+   // SET_DMA1_CH3_CCR_PINC_BIT();                                                 //Peripheral increment mode
+   
 void initDMA() {
+    //-----------------------------------------------Step-1-----------------------------------------------------------------------------------------------------------
     RCC->AHB1ENR|= (RCC_AHB1ENR_DMA1EN);                                        //Enable the DMA1 clock
     
+    //-----------------------------------------------Step-2-----------------------------------------------------------------------------------------------------------
     DMA1_CH2_DISABLE();                                                         //Disable DMA channel 2
     DMA1_CH3_DISABLE();                                                         //Disable DMA channel 3
     
     SET_DMA1_SPI1RX_CSELR_BITS();                                               //Select SPI1_Rx on DMA1 Channel 2
     SET_DMA1_SPI1TX_CSELR_BITS();                                               //Select SPI1_Tx on DMA1 Channel 3
-                    
+     
+    //-----------------------------------------------Step-3-----------------------------------------------------------------------------------------------------------                 
 //-----------------------------------------------Receive-----------------------------------------------------                         
-   CLEAR_DMA1_CH2_CCR_DIR_BIT();                                                //Peripheral->Memory
-   SET_DMA1_CH2_CCR_PSIZE_BITS();                                               //16 bits
-   SET_DMA1_CH2_CCR_MSIZE_BITS();                                               //16 bits
-   SET_DMA1_CH2_CCR_MINC_BIT();                                                 //Memory increment mode
-   //SET_DMA1_CH2_CCR_PINC_BIT();                                                 //Peripheral increment mode
-   SET_DMA1_CH2_CCR_TCIE_BIT();                                                 //Transfer complete interrupt enable
-   SET_DMA1_CH2_CCR_CIRC_BIT();                                                 //Circular Buffer mode
+   CLEAR_DMA1_CH2_CCR_DIR_BIT();                                                //Direction bit: 0 = Peripheral->Memory. Data will be loaded from SPI data register to the specified variable
+   SET_DMA1_CH2_CCR_PSIZE_BITS();                                               //peripheral size bit: 1 = 16 bits. The size is set to 16 bits as thats the data size SPI will work in.
+   SET_DMA1_CH2_CCR_MSIZE_BITS();                                               //Memory size bit: 1 = 16 bits. The size is set to 16 bits as data coming from SPI is 16 bits wide
+   SET_DMA1_CH2_CCR_MINC_BIT();                                                 //Memory increment mode but: 1 = Increment memory after each transaction. Used when multiple transaction are done before interrupt occurs
+   SET_DMA1_CH2_CCR_TCIE_BIT();                                                 //Transfer complete interrupt enable: 1 = enabled. Allows DMA to interrupt software when number of transaction has occured.
+   SET_DMA1_CH2_CCR_CIRC_BIT();                                                 //Circular Buffer mode: 1 = enabled. After n transaction, the address is reset to starting memory address automatically.
    SET_DMA1_CH2_CCR_PL_BITS();                                                  //Priority Level = Highest
                         
-    DMA1_Channel2->CNDTR = 12;                                                  //number of data to transfer from the peripheral to memory.
+    DMA1_Channel2->CNDTR = 12;                                                  //number of data to transfer from the peripheral to memory before interrupt occurs.
     DMA1_Channel2->CPAR = (int32_t)&SPI1->DR;                                   //Source Adddress = SPI data register
-    DMA1_Channel2->CMAR = (int32_t)&received_data[0];                               //Destination address = received_data array
+    DMA1_Channel2->CMAR = (int32_t)&received_data[0];                           //Destination address = received_data array.
 //-----------------------------------------------Receive-----------------------------------------------------   
     
+    
+    
 //-----------------------------------------------Transmission------------------------------------------------  
 
-   SET_DMA1_CH3_CCR_DIR_BIT();                                                  //Memory->Peripheral
-   SET_DMA1_CH3_CCR_PSIZE_BITS();                                               //16 bits
-   SET_DMA1_CH3_CCR_MSIZE_BITS();                                               //16 bits
+   SET_DMA1_CH3_CCR_DIR_BIT();                                                  //Direction bit: 1 = Memory->Peripheral. Data will be sent from variable to SPI data register for transmission
+   SET_DMA1_CH3_CCR_PSIZE_BITS();                                               //peripheral size bit: 1 = 16 bits. The size is set to 16 bits as thats the data size SPI will work in.
+   SET_DMA1_CH3_CCR_MSIZE_BITS();                                               //Memory size bit: 1 = 16 bits. The size is set to 16 bits as data coming from SPI is 16 bits wide
    SET_DMA1_CH3_CCR_MINC_BIT();                                                 //Memory increment mode
-  // SET_DMA1_CH3_CCR_PINC_BIT();                                                 //Peripheral increment mode
    SET_DMA1_CH3_CCR_TCIE_BIT();                                                 //Transfer complete interrupt enable
    SET_DMA1_CH3_CCR_CIRC_BIT();                                                 //Circular Buffer mode
    SET_DMA1_CH3_CCR_PL_BITS();                                                  //Priority Level = Highest
                       
-    DMA1_Channel3->CNDTR = 12;                                                 //number of data to transfer from memory to the peripheral
+    DMA1_Channel3->CNDTR = 12;                                                  //number of data to transfer from memory to the peripheral to be transmitted.
     DMA1_Channel3->CPAR = (int32_t)&SPI1->DR;                                   //Destination address = SPI data register
-    DMA1_Channel3->CMAR = (int32_t)&data_to_transmit[0];                            //Source address = data_to_transmit
+    DMA1_Channel3->CMAR = (int32_t)&data_to_transmit[0];                        //Source address = data_to_transmit: Address from which data will be loaded to the SPI data register for transmission
 //-----------------------------------------------Transmission------------------------------------------------    
-    
-    
-    NVIC->ISER[0] |= (1u<<12);                                                   //Enable DMA1 channel 2 interrupt                                                   
-    NVIC->ISER[0] |= (1u<<13);                                                   //Enable DMA1 channel 3 interrupt
+//-----------------------------------------------Step-4-----------------------------------------------------------------------------------------------------------     
+    //Enable DMA1 channel 2 and 3 interrupts    
+    NVIC->ISER[0] |= (1u<<12);                                                                                                  
+    NVIC->ISER[0] |= (1u<<13);                                                 
     NVIC_EnableIRQ(DMA1_Channel2_IRQn);
-    NVIC_EnableIRQ(DMA1_Channel3_IRQn);
-                      
+    NVIC_EnableIRQ(DMA1_Channel3_IRQn);                   
 }
 
 
@@ -241,16 +248,11 @@
 extern "C" void DMA1_Channel2_IRQHandler(void) {
      uint16_t n;
      
-     CLEAR_DMA1_CH2_IFCR_GFLAG();                                               //Clear Global Interrupt flag
-     for(int x = 0; x <= 11; x++) {
-        
-        n = received_data[x];
-        n &= ~(8191);                                                     //remove first 13 bits
-        n = n >> 13;                                            //shift by right by 13
-        SampleFIFO[pointerFS][x] = received_data[x];
-       // printf("%d \n\r", n);
+     CLEAR_DMA1_CH2_IFCR_GFLAG();                                               //Clear Global Interrupt flag so that the nterrupt can occur again once a new batch of data is received.
+     for(int x = 0; x <= 11; x++) {                                             //run the for loop to read new data from the array that the SPI uses to save the received data to a new array to avoid overwritting
+        SampleFIFO[pointerFS][x] = received_data[x];                            //Just move the data from one array to the other.
     }
-    newDataFlag = 1;
+    newDataFlag = 1;                                                            //Once new data has been read set this flag to notify software that new data is received so that it proceeds with processing it.
 }