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

Dependencies:   mbed

Revision:
9:9ed9dffd602a
Parent:
8:e87027349167
Child:
10:5b96211275d4
--- a/DMA_SPI.cpp	Wed Feb 27 23:35:51 2019 +0000
+++ b/DMA_SPI.cpp	Thu Mar 07 01:16:48 2019 +0000
@@ -1,49 +1,229 @@
 #include "mbed.h"
 #include "DMA_SPI.h"
 
-extern int16_t data_to_transmit[6];
-extern int16_t received_data[12];
+int16_t data_to_transmit[12];
+int16_t received_data[12];
+DigitalOut myled(LED1);
+
+void SPI_DMA_init() {
+    myled = 1;                                                                  //toggle LED on
+    
+    //Deinitialise
+    SPI_DMA_SLAVE_deinit();
+    deinitDMA();
+    
+    //Initialise
+    initDMA();
+    SPI_DMA_SLAVE_init(); 
+    
+    //Start DMA communication
+    startCommunication();     
+}    
+
+/* Starting DMA communication according to STM32L432 Reference Manual p1317-p1318*/
+void startCommunication() {
+    
+    SET_SPI1_CR2_RXDMAEN_BIT();                                                 //Enable RX DMA buffer
+    DMA1_CH3_ENABLE();                                                          //Enable DMA channel 3      
+    DMA1_CH2_ENABLE();                                                          //Enable DMA channel 2
+    SET_SPI1_CR2_TXDMAEN_BIT();                                                 //Enable TX DMA buffer              
+    SPI1_ENABLE();                                                              //SPI module enabled
+}
+
+
+//====================================================DEINITIALISE=========================================================================
+void SPI_DMA_SLAVE_deinit() {
+    //Disable the clocks
+    //RCC->AHB2ENR &= ~(RCC_AHB2ENR_GPIOAEN);                                      
+    //RCC->APB2ENR &=  ~(RCC_APB2ENR_SPI1EN);      
+    //Clear pin settings
+    GPIOA->MODER&=~((3u<<(2*CS_slave)));                                         //clear GPIOA pin mode (in input mode when reset)
+    
+    GPIOA->MODER&=~(                                                             //clear GPIOB
+            (3u<<(2*SCK_slave))
+            |(3u<<(2*MISO_slave))
+            |(3u<<(2*MOSI_slave))
+            |0x03
+                );
+
+    GPIOA->AFR[0]&=~(                                                            //clear alternate function selector bits
+            (0x0f<<(4*SCK_slave))
+            |(0x0f<<(4*MISO_slave))
+            |(15u<<(4*MOSI_slave))
+            );
+    
+    //Clear SPI bits
+    SPI1_DISABLE();
+    CLEAR_SPI1_CR1_MSTR_BIT();
+    CLEAR_SPI1_CR1_BR_BITS();
+    CLEAR_SPI1_CR1_SSM_BIT();
+    CLEAR_SPI1_CR1_SSI_BIT();
+    CLEAR_SPI1_CR1_CPOL_BIT();
+    CLEAR_SPI1_CR1_CPHA_BIT();
+    
+    
+    CLEAR_SPI1_CR2_DS_BITS();
+    CLEAR_SPI1_CR2_RXDMAEN_BIT();
+    CLEAR_SPI1_CR2_TXDMAEN_BIT();
+    CLEAR_SPI1_CR2_RXEIE_BIT();
+    CLEAR_SPI1_CR2_TXEIE_BIT();
+    
+    CLEAR_SPI1_CR1_CRC_BIT();
+    
+     RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST;
+     RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1RST;
+}
+
+void deinitDMA() {
+    //RCC->AHB1ENR &= ~(RCC_AHB1ENR_DMA1EN);                                      //Disable the DMA1 clock
+    RCC->AHB1RSTR |= RCC_AHB1RSTR_DMA1RST;
+    RCC->AHB1RSTR &= ~RCC_AHB1RSTR_DMA1RST;
+    
+    //Disable channels
+    DMA1_CH2_DISABLE();
+    DMA1_CH3_DISABLE();
+    
+    CLEAR_DMA1_SPI1RX_CSELR_BITS();                                             //deselect SPI1_Rx on DMA1 Channel 2
+    CLEAR_DMA1_SPI1TX_CSELR_BITS();                                             //deselect SPI1_Tx on DMA1 Channel 3
+     
+                    
+//-----------------------------------------------Receive-----------------------------------------------------                       
+   //Clear configuration bits                     
+   CLEAR_DMA1_CH2_CCR_DIR_BIT();                                                
+   CLEAR_DMA1_CH2_CCR_PSIZE_BITS();
+   CLEAR_DMA1_CH2_CCR_MSIZE_BITS();
+   CLEAR_DMA1_CH2_CCR_MINC_BIT();
+   CLEAR_DMA1_CH2_CCR_PINC_BIT();
+   CLEAR_DMA1_CH2_CCR_TCIE_BIT();
+   CLEAR_DMA1_CH2_CCR_CIRC_BIT();
+   CLEAR_DMA1_CH2_CCR_MEM2MEM_BIT();
+   CLEAR_DMA1_CH2_CCR_PL_BITS();
+   CLEAR_DMA1_CH2_CCR_TEIE_BIT();
+   
+   CLEAR_DMA1_CH2_CNDTR_BITS();
+   CLEAR_DMA1_CH2_CPAR_BITS();
+   CLEAR_DMA1_CH2_CMAR_BITS();
+//-----------------------------------------------Receive-----------------------------------------------------   
+    
+//-----------------------------------------------Transmission------------------------------------------------  
+    //Clear configuration bits 
+    CLEAR_DMA1_CH3_CCR_DIR_BIT();
+    CLEAR_DMA1_CH3_CCR_PSIZE_BITS();
+    CLEAR_DMA1_CH3_CCR_MSIZE_BITS();
+    CLEAR_DMA1_CH3_CCR_MINC_BIT();
+    CLEAR_DMA1_CH3_CCR_PINC_BIT();
+    CLEAR_DMA1_CH3_CCR_TCIE_BIT();
+    CLEAR_DMA1_CH3_CCR_CIRC_BIT();
+    CLEAR_DMA1_CH3_CCR_MEM2MEM_BIT();
+    CLEAR_DMA1_CH3_CCR_PL_BITS();
+    CLEAR_DMA1_CH3_CCR_TEIE_BIT();
+    
+    CLEAR_DMA1_CH3_CNDTR_BITS();
+    CLEAR_DMA1_CH3_CPAR_BITS();
+    CLEAR_DMA1_CH3_CMAR_BITS();
+    
+//-----------------------------------------------Transmission------------------------------------------------    
+    
+    NVIC->ISER[0]&= ~(1u<<12);                                                   //Disable DMA1 channel 2 interrupt                                                   
+    NVIC->ISER[0]&= ~(1u<<13);                                                   //Disable DMA1 channel 3 interrupt
+      
+}
+//====================================================DEINITIALISE=========================================================================
+
+
+
+void SPI_DMA_SLAVE_init() {
+    RCC->AHB2ENR|= (RCC_AHB2ENR_GPIOAEN);                                       //GPIO A clock enable       
+    RCC->APB2ENR|=RCC_APB2ENR_SPI1EN;                                           //Enable SPI1 Clock
+
+   //SET SCK, MISO, MOSI and CS pins 
+    GPIOA->MODER|=(                                                             
+            (2u<<(2*SCK_slave))
+            |(2u<<(2*MISO_slave))
+            |(2u<<(2*MOSI_slave))
+            |0x01
+                );
+                
+    //SET pins to function as SPI pins
+    GPIOA->AFR[0]|=(                                                             
+            (5u<<(4*SCK_slave))
+            |(5u<<(4*MISO_slave))
+            |(5u<<(4*MOSI_slave))
+                );
+                
+    SET_SPI1_CR1_BR_BITS();                                                     //baud rate bits set 1/16 giving 1MHz SCK frequency
+    SET_SPI1_CR1_CPOL_BIT();                                                    //CPOL = 1
+    SET_SPI1_CR1_CPHA_BIT();                                                    //CPHA = 1                                                  
+    
+    
+    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
+
+    
+}
+
+
 
 void initDMA() {
-    RCC->AHB1ENR|= (RCC_AHB1ENR_DMA1EN);                                        //Enable the DMA clock
+    RCC->AHB1ENR|= (RCC_AHB1ENR_DMA1EN);                                        //Enable the DMA1 clock
+    
+    DMA1_CH2_DISABLE();                                                         //Disable DMA channel 2
+    DMA1_CH3_DISABLE();                                                         //Disable DMA channel 3
     
-    DMA1->DMA1_CSELR |= (
-                        (0x01<<(4*(C2S - 1)))                                   //Select SPI1_Rx on DMA1 Channel 2
-                        |(0x01<<(4*(C3S - 1)))                                  //Select SPI1_Tx on DMA1 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
                     
-                    
+//-----------------------------------------------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
+   SET_DMA1_CH2_CCR_PL_BITS();                                                  //Priority Level = Highest
                         
-    DMA1->DMA1_CCR2 &= ~((0x01 << 4));                                           //Clear bit 4 in channel 2 configuration register to set the channel to read from peripheral. Peripheral -> Memory
-    DMA1->DMA1_CCR2 |= ((0x01 << 8)                                              //Set peripheral size to 16-bits
-                       |(0x01 << 10)                                            //Set memory size to 16-bits
-                       |(0x01 << 7)                                             //Set to memory increment mode
-                       |(0x01 << 1)                                             //Transfer complete interrupt enable
-                       );
-                       
-    DMA1->DMA1_CNDTR2 = 12;                                                      //number of data to transfer from the peripherla to memory
-    DMA1->DMA1_CPAR2 = SPI1->DR;
-    DMA1->DMA1_CMAR2 = received_data;
+    DMA1_Channel2->CNDTR = 12;                                                  //number of data to transfer from the peripheral to memory.
+    DMA1_Channel2->CPAR = (int32_t)&SPI1->DR;                                   //Source Adddress = SPI data register
+    DMA1_Channel2->CMAR = (int32_t)received_data;                               //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_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->CPAR = (int32_t)&SPI1->DR;                                   //Destination address = SPI data register
+    DMA1_Channel3->CMAR = (int32_t)data_to_transmit;                            //Source address = data_to_transmit
+//-----------------------------------------------Transmission------------------------------------------------    
     
     
-    DMA1->DMA1_CCR3 |=  ((0x01 << 4));                                           //Clear bit 4 in channel 3 configuration register to set the channel to read from memory.   Memroy -> Peripheral                   
-    DMA1->DMA1_CCR3 |= ((0x01 << 8)                                              //Set peripheral size to 16-bits
-                      |(0x01 << 10)                                             //Set memory size to 16-bits
-                      |(0x01 << 7)                                              //Set to memory increment mode
-                      |(0x01 << 1)                                              //Transfer complete interrupt enable
-                      );
-                      
-    DMA1->DMA1_CNDTR3 = 6;                                                       //number of data to transfer from memory to the peripheral
-    DMA1->DMA1_CPAR3 = SPI1->DR;
-    DMA1->DMA1_CMAR3 = data_to_transmit;
-    
-    
-    DMA1->DMA1_CCR2 |= (0x01<<0);                                                //Enable channel 2. Must be disabled in order to be able to alter DMA
-    DMA1->DMA_CCR3 |= (0x01<<0);                                                //Enable channel 3. Must be disabled in order to be able to alter DMA
-    
-    
-    NVIC->ISER[0]|= (1u<<12);                                                   //Enable DMA1 channel 2 interrupt                                                   
-    NVIC->ISER[0]|= (1u<<13);                                                   //Enable DMA1 channel 3 interrupt
-    //NVIC_EnableIRQ(EXTI15_10_IRQn);                                             //enable the interrupt request
+  //  NVIC->ISER[0]|= (1u<<12);                                                   //Enable DMA1 channel 2 interrupt                                                   
+  //  NVIC->ISER[0]|= (1u<<13);                                                   //Enable DMA1 channel 3 interrupt
+  //  NVIC_EnableIRQ(DMA1_Channel2_IRQn);
+  //  NVIC_EnableIRQ(DMA1_Channel3_IRQn);
                       
 }
+
+
+//Interrupt Handler for DMA1 Channel 2
+void DMA1_Channel2_IRQHandler(void) {
+     myled = 0;                                                                 //Toggle LED off
+     CLEAR_DMA1_CH2_IFCR_GFLAG();                                               //Clear Global Interrupt flag
+}
+
+
+//Interrupt Handler for DMA1 Channel 3
+void DMA1_Channel3_IRQHandler(void) {
+     myled = 0;  
+     CLEAR_DMA1_CH3_IFCR_GFLAG();                                               //Clear Global Interrupt flag             
+}
+