
SPI slave program to enable communication between the FPGA and the STM32L432 board.
DMA_SPI.cpp
- Committer:
- Zbyszek
- Date:
- 2019-04-19
- Revision:
- 13:c7e8e277f884
- Parent:
- 12:3e7da86a49ff
- Child:
- 14:7bbaafa22f8d
File content as of revision 13:c7e8e277f884:
#include "mbed.h" #include "DMA_SPI.h" int16_t data_to_transmit[12]; int16_t received_data[12]; int16_t IMU_Data_Array[12]; int16_t SampleFIFO[10][12]; extern int pointerOS = 0; extern int pointerNS = 0; extern int pointerFS = 0; extern char newDataFlag = 0; volatile extern char dataRequestFlag = 0; volatile extern char dataLoadedFlag = 0; void SPI_DMA_init() { //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&=~( //clear GPIOB (3u<<(2*SCK_slave)) |(3u<<(2*MISO_slave)) |(3u<<(2*MOSI_slave)) |(3u<<(2*4)) ); GPIOB->MODER &= ~(2u<<0); GPIOA->AFR[0]&=~( //clear alternate function selector bits (0x0f<<(4*SCK_slave)) |(0x0f<<(4*MISO_slave)) |(15u<<(4*MOSI_slave)) //|(15u<<(2*4)) //Thhis is why the UART was not working ); GPIOB->AFR[0] &= ~(15u<<(4*0)); //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->AHB2ENR |= (RCC_AHB2ENR_GPIOBEN); 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)) //|(2u<<(2*4)) ); //Set PB_0 to alternate function GPIOB->MODER |= (2u<<0); //SET pins to function as SPI pins GPIOA->AFR[0]|=( (5u<<(4*SCK_slave)) |(5u<<(4*MISO_slave)) |(5u<<(4*MOSI_slave)) //|(5u<<(4*4)) ); //Select SPI1_SSEL alternate function GPIOB->AFR[0] |= (5u<<(4*0)); 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 DMA1 clock 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 //-----------------------------------------------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_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[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_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[0]; //Source address = data_to_transmit //-----------------------------------------------Transmission------------------------------------------------ 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 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); } newDataFlag = 1; } //Interrupt Handler for DMA1 Channel 3 extern "C" void DMA1_Channel3_IRQHandler(void) { if(DMA1->ISR&(1u<<9)) { //Check whteher data transmit transfer is complete //Read data from the array that stores received data if(dataRequestFlag == 1 && dataLoadedFlag == 1) { for(int x = 0; x <= 11; x++) { if(x < 7) { //Data is only loaded in first 7 places if(x == 0) { //IMU ID is loaded in array position 0 data_to_transmit[x] = IMU_Data_Array[x]; //Load the IMU data for transmission // data_to_transmit[x] = 1; //Test Input } else { //Rest is loaded in the following order: x, y, z data_to_transmit[x] = IMU_Data_Array[x]; //Load the IMU data for transmission //data_to_transmit[x] = 48+x; //Test Input } } else { //After 7 positions have been filled, the rest is filled with zeros data_to_transmit[x] = 0; //Above 6 there is nothing more to send so send zeros. } } dataRequestFlag = 0; //Data request has been fulfilled and therefore clear the flag } else { //if the two flags arent 1 then load this transmission with zeros for(int x = 0; x <= 11; x++) { data_to_transmit[x] = 0; } } CLEAR_DMA1_CH3_IFCR_GFLAG(); //Clear global channel interrupt flag for channel 3 } //Clear Global Interrupt flag }