SPI1 + DMA Interrupt setup for RX only from a peripheral sensor (Nucleo-F767ZI)
Hello Everyone,
So, I am trying to configure the SPI1 to work with DMA so I can fill in a buffer from my sensor for every occurring interrupt, so when the buffer is full and I can send it to my client server.
I used CubeMX to configure SPI1 and DMA2 Stream2 for SPI1_RX. I enabled both DMA and SPI1 global interrupts.
I am confused in understand how the IRQ handler gets called, because I assume I need to fill my buffer during that routine. However, it never gets called. Below are the initialization and my code.
Thank you !
This is from CubeMX
**
* @brief SPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hspi: SPI handle pointer
* @retval None
*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI1)
{
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PD7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = SPI_SCK_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(SPI_SCK_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI_MISO_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(SPI_MISO_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SPI_MOSI_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(SPI_MOSI_GPIO_Port, &GPIO_InitStruct);
/* SPI1 DMA Init */
/* SPI1_RX Init */
hdma_spi1_rx.Instance = DMA2_Stream2;
hdma_spi1_rx.Init.Channel = DMA_CHANNEL_3;
hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi1_rx);
/* SPI1 interrupt Init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
}
MY CODE
void dma_start(void){
/* pull CS low to enable SPI transfer */
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
/* read line from the SPI in 16 bits
* For video packets, the header includes a 2-byte(16bits) ID
* and a 2-byte (16 bits) CRC.
*/
HAL_SPI_TransmitReceive_DMA(&hspi1, &frame_packet[0],&frame_packet[0], FRAME_SIZE/2);
}
/**
* @brief This function handles DMA2 stream2 global interrupt.
*/
void DMA2_Stream2_IRQHandler(void)
{
/* keep track of the number of lines */
int line_number=0;
static int expected_line_number = 0;
/* keep synchronization*/
static int sync_count = 0;
HAL_DMA_IRQHandler(&hdma_spi1_rx);
/* pull CS HIGH to end SPI transfer */
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
/* Examine the ID field of the packet, identifying a discard packet (xFxx). */
if((frame_packet[0] & 0xf00) != 0xf00)
{
/* store line number */
line_number = frame_packet[0] & 0xff;
/* check input line number and copy lepton buffer data consecutively */
if (line_number < NUMBER_OF_ROWS && line_number == expected_line_number){
memcpy(&lepton_image[line_number], &frame_packet[2], FRAME_PAYLOAD);
/* update line number */
expected_line_number = line_number+1;
/* check when full frame is transferred, 59 packets for raw14 mode */
if (line_number == (NUMBER_OF_ROWS - 1)) {
// data_server_send("s", 1);
// data_server_send((char*)lepton_image, sizeof(lepton_image));
}
}
else {
/* Deassert /CS and idle SCK for at least 5 frame periods (>185 msec).
* This step ensures a timeout of the VoSPI interface,
* which puts the Lepton in the proper state to establish
* (or re-establish) synchronization*/
HAL_Delay(200);
expected_line_number = 0;
sync_count++;
}
}
}
Once I call TramsitReceive_DMA, isnt supposed to jump to the IRQ handler?
In my main, I do dma_start() before the while loop.