
SPI slave program to enable communication between the FPGA and the STM32L432 board.
Diff: DMA_SPI.cpp
- 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 +} +